View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0022980 | Community | OCCT:Foundation Classes | public | 2012-02-07 12:33 | 2013-04-29 15:21 |
Reporter | Roman Lygin | Assigned To | Roman Lygin | ||
Priority | normal | Severity | minor | ||
Status | closed | Resolution | fixed | ||
Platform | A | OS | L | ||
Product Version | 6.5.2 | ||||
Target Version | 6.6.0 | Fixed in Version | 6.6.0 | ||
Summary | 0022980: Fixed Standard_Atomic.hxx | ||||
Description | In 6.5.0 and 6.5.1 Standard_Atomic_Increment() on gcc/Linux (and MacOS) lacked clobber statement "memory" what resulted in wrong results when working in highly contended mode. Also Standard_Atomic_Decrement() used wrong int volatile* which also resulted in wrong result in highly contended mode. The fix includes merge with 6.5.2 and the following: - correct use of volatile int* instead of int volatile*; - use of __GNUC__ macros instead of LIN (which is non-standard OCC-specific macro), to also enable use on MacOS/Intel; - minimized code (use of fetch-and-add semantic Standard_Atomic_Add() which is called by Increment() and Decrement()) inspired by boost/atomic.hpp. Performance impact should be marginal, if at all comparing to code in 6.5.2 (using xaddl and incl); - note that built-in atomic routines are available as of gcc4.1, even if macro __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 is not defined but we do not use it (see comments in Standard_Atomic.hxx for reasoning); - minor grammar mistakes The fix can be applied to 6.5.0, 6.5.1, 6.5.2. Reproducer: see Standard_AtomicTest | ||||
Steps To Reproduce | See Standard_Atomic_Test.cxx | ||||
Tags | No tags attached. | ||||
Test case number | bugs fclasses(002) bug22980 | ||||
parent of | 0023657 | closed | Open CASCADE | Fails compilation with WOK after patch 22980 |
|
Standard_Atomic_fix.zip (2,147 bytes) |
|
Dear Roman, could you please update patch according to new rules (in git branch)? >>Also Standard_Atomic_Decrement() used wrong int volatile* >> which also resulted in wrong result in highly contended mode. Could you please clarify this? _InterlockedIncrement() definition exactly fits Microsoft headers (volatile keyword usage, see WinBase.h - checked in Visual Studio 2008/2010). Moreover it looks like "volatile int* " and "int volatile* " means the same thing (but not "int* volatile "). >>inline int Standard_Atomic_DecrementTest (volatile int* theValue) Standard_Atomic_DecrementTest() function was removed because it is pointless. Is it really so useful alias to be widely used in application code? >> #elif defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) >> // || (__GNUC__ >= 4 && __GNUC_MINOR__ >= 1) Modern gcc SHOULD define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 to indicate that current platform supports atomic operations on 32bit integers. If we want to support these built-in functions in older versions of gcc we should check something like this instead: >> #elif defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) >> || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1 && __GNUC_MINOR__ < 4) However current build scripts do not add -march=i486 argument on 32-bit Linux so it will result in linker errors. But probably this is more correct to update our building procedures too (this is pointless to support ancient i386 today). >>use of fetch-and-add semantic Standard_Atomic_Add() >>int Standard_Atomic_Add (volatile int* theValue, int theVal) First, function entirely defined in header and should have inline keyword to avoid compiler/linker errors. Second - it is misconception to declare global function implemented only in one rare case. It should be either implemented for other scenarios (using __sync_sub_and_fetch() / WinAPI) or its definition should be hidden to user. More hints: - Functions duplicated several times for each implementation. This is more convenient (more compact, less duplication, slightly less error-prone) to use platform-dependent macros inside function body instead. - Use MacOS X functions in case when gcc built-ins unavailable: #if defined(__APPLE__) #include <libkern/OSAtomic.h> int Standard_Atomic_Increment (volatile int* theValue) { return OSAtomicIncrement32Barrier(theValue); } int Standard_Atomic_Decrement (volatile int* theValue) { return OSAtomicDecrement32Barrier (theValue); } #endif |
|
Pushed branch CR22980 into the git repository Kirill, thanks a lot for detailed comments and sorry for delayed response on my side. Here are responses. 1. Windows: volatile long* vs long volatile*. There is apparently inconsistency in MSFT itself. WinBase.h (in Windows SDK 7.0) has: InterlockedIncrement ( __inout LONG volatile *lpAddend ); see also http://msdn.microsoft.com/en-us/library/windows/desktop/ms683614%28v=vs.85%29.aspx (although this is not intrinsic function) but the compiler VS2008 has both: in intrin.h: __MACHINEI(long __cdecl _InterlockedIncrement(long volatile *)) in <memory>: extern "C" long __CLRCALL_PURE_OR_CDECL _InterlockedIncrement(volatile long *); extern "C" long __CLRCALL_PURE_OR_CDECL _InterlockedDecrement(volatile long *); extern "C" long __CLRCALL_PURE_OR_CDECL _InterlockedCompareExchange(volatile long *, long, long); #pragma intrinsic(_InterlockedIncrement) #pragma intrinsic(_InterlockedDecrement) #pragma intrinsic(_InterlockedCompareExchange) Thus, it seems it does not matter and either is fine. If you feel uncomfortable with current 'volatile long*' change otherwise. 2. OK to remove Standard_Decrement_Test(). I will make my own copy as needed. 3. __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 Let's keep the current version as is, i.e. to only check for explicit presence of __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4. Thus, the modification will preserve current OCC behavior. Adding -march should be a separate issue. I have removed confusing // || (__GNUC__ >= 4 && __GNUC_MINOR__ >= 1). but left the rest of the comment for information, if anyone tries to use these built-in functions on earlier gcc versions. 4. Standard_Atomic_Add() 4a. Added inline - initially was my oversight, sorry about that. This was a copy past of non-inlined functions in Standard_Atomic.hxx - note missing 'inline' there too ;-). 4b. There is no "misconception" - Standard_Atomic_Add() is used by Standard_Atomic_Increment() and Standard_Atomic_Decrement() which are defined in this very file. Please elaborate if you meant something different. 5. Hints a. Code structure. I intentionally separated implementations per OSes/compilers for better code clarity instead of putting everything inside the same function. Single line function is better to read than contamination of platform-specific codes, when only a declaration line is common. Another advantage is that you can put comments common for both Increment() and Decrement() only once at the top of the specific section. However this can be subjective, so I'd delegate final resolution to ABV. b. MacOS. Thanks, I have added these to be chosen if gcc built-ins are not available (which is likely for MacOS 10.x given that gcc version is < 4.4). But this was not tested on my side. Please review and amend during real port. Thanks again for detailed comments. Hope these amendments address your concerns. Please let me know if there is anything you would like to follow up on. |
|
Patch is ready for testing. Please check compilation on Mac OS X as well. |
|
Dear BugMaster, Branch CR22980 (and products from GIT master) was compiled on Linux and Windows platforms and tested. Regressions: Not detected Improvements: Not detected Testing cases: bugs fclasses(002) bug22980 - KO. http://occt-tests/CR22980-master-occt/Windows-32-VC9/bugs/fclasses/bug22980.html |
|
The corrected test is pushed to CR22980, please test and integrate |
|
Dear BugMaster, Branch CR22980 (and products from GIT master) was compiled on Linux and Windows platforms. There is compilation error on Linux: ../../../src/QABugs/QABugs_19.cxx:206: error: 'argv' was not declared in this scope |
|
Fix for building with TBB disabled pushed to branch CR22980, please test. Please make sure to have TBB enabled for testing! |
|
Dear BugMaster, Branch CR22980 (and products from GIT master) was compiled on Linux and Windows platforms and tested. Regressions: Not detected Improvements: Not detected Testing cases: bugs fclasses(002) bug22980 - OK. |
occt: master 1365140b 2012-12-18 18:35:43 Details Diff |
0022980: Fixed Standard_Atomic.hxx Standard_Atomic, prefer gcc built-ins rather than WinAPI calls (revert previous change of order) Raise compiler error if no implementation found for atomic operations. Add new draw command for testing this bug Fix for compilation with TBB disabled Adding CSF_TBB_INCLUDES macro in edl files Correction of *.edl files Update of EXTERNLIB files with CSF_TBB Adding EXTERNLIB file |
Affected Issues 0022980 |
|
mod - src/Draw/Draw_CMPLRS.edl | Diff File | ||
mod - src/Draw/EXTERNLIB | Diff File | ||
add - src/QABugs/EXTERNLIB | Diff File | ||
mod - src/QABugs/FILES | Diff File | ||
mod - src/QANCollection/QANCollection1.cxx | Diff File | ||
mod - src/QANCollection/QANCollection2.cxx | Diff File | ||
mod - src/QANCollection/QANCollection3.cxx | Diff File | ||
mod - src/Standard/Standard_Atomic.hxx | Diff File | ||
mod - src/Standard/Standard_CMPLRS.edl | Diff File | ||
mod - src/TKDraw/EXTERNLIB | Diff File | ||
mod - src/TKQADraw/EXTERNLIB | Diff File | ||
add - tests/bugs/fclasses/bug22980 | Diff File |
Date Modified | Username | Field | Change |
---|---|---|---|
2012-02-07 12:33 | Roman Lygin | New Issue | |
2012-02-07 12:33 | Roman Lygin | Assigned To | => abv |
2012-02-07 12:33 | Roman Lygin | File Added: Standard_Atomic_fix.zip | |
2012-05-04 13:00 |
|
Status | new => assigned |
2012-08-14 09:10 | kgv | Assigned To | abv => Roman Lygin |
2012-08-14 09:43 | kgv | Note Added: 0021235 | |
2012-10-24 17:32 |
|
Target Version | => 6.6.0 |
2012-11-28 16:36 | Roman Lygin | Note Added: 0022413 | |
2012-11-28 16:36 | Roman Lygin | Assigned To | Roman Lygin => kgv |
2012-11-28 16:36 | Roman Lygin | Status | assigned => resolved |
2012-12-02 17:50 | kgv | Note Added: 0022499 | |
2012-12-02 17:50 | kgv | Assigned To | kgv => bugmaster |
2012-12-02 17:50 | kgv | Status | resolved => reviewed |
2012-12-03 18:58 |
|
Assigned To | bugmaster => mkv |
2012-12-07 14:52 |
|
Note Added: 0022624 | |
2012-12-07 14:53 |
|
Test case number | => bugs fclasses(002) bug22980 |
2012-12-07 14:53 |
|
Assigned To | mkv => kgv |
2012-12-07 14:53 |
|
Status | reviewed => assigned |
2012-12-10 16:19 |
|
Assigned To | kgv => abv |
2012-12-11 00:56 |
|
Note Added: 0022642 | |
2012-12-11 00:56 |
|
Assigned To | abv => mkv |
2012-12-11 00:56 |
|
Status | assigned => resolved |
2012-12-11 00:56 |
|
Status | resolved => reviewed |
2012-12-12 09:44 |
|
Note Added: 0022665 | |
2012-12-12 09:45 |
|
Assigned To | mkv => abv |
2012-12-12 09:45 |
|
Status | reviewed => assigned |
2012-12-12 09:46 |
|
Note Edited: 0022665 | |
2012-12-12 10:36 |
|
Note Added: 0022667 | |
2012-12-12 10:36 |
|
Status | assigned => resolved |
2012-12-12 10:36 |
|
Assigned To | abv => mkv |
2012-12-12 10:36 |
|
Status | resolved => reviewed |
2012-12-18 15:15 |
|
Note Added: 0022745 | |
2012-12-18 15:15 |
|
Assigned To | mkv => bugmaster |
2012-12-18 15:15 |
|
Status | reviewed => tested |
2012-12-21 15:58 | Roman Lygin | Changeset attached | => occt master 1365140b |
2012-12-21 15:58 | Roman Lygin | Assigned To | bugmaster => Roman Lygin |
2012-12-21 15:58 | Roman Lygin | Status | tested => verified |
2012-12-21 15:58 | Roman Lygin | Resolution | open => fixed |
2013-01-09 02:51 |
|
Relationship added | parent of 0023657 |
2013-04-23 13:36 |
|
Status | verified => closed |
2013-04-29 15:21 |
|
Fixed in Version | => 6.6.0 |