Re: [PATCH] Fix ODR violations in code using
On 05/07/19 19:44 +0100, Jonathan Wakely wrote: On 05/07/19 20:23 +0200, Daniel Krügler wrote: Am Fr., 5. Juli 2019 um 18:13 Uhr schrieb Jonathan Wakely : [..] I decided against the simplification in the second patch, and committed the attached one which is closer to the first patch I sent (preserving the __atomic_add and __exchange_and_add functions even when they just call the built-ins). Tested x86_64-linux, powerpc64-linux, powerpc-aix. Committed to trunk. Unrelated to the actual patch, I noticed some explicit "throw()" forms used as exception specifications - shouldn't these be replaced by either explicit "noexcept" or at least by a library macro that expands to one or the other? Yes, they should be _GLIBCXX_NOTHROW. (I'm sorry, if such unrelated questions are considered as inappropriate for this list). Entirely appropriate, thanks! Here's a patch to fix that and the dumb mistake I made in __atomic_add_dispatch. I'll commit after testing finishes. commit 1542776ebab8848109d125d05a548fca5efb513a Author: Jonathan Wakely Date: Sat Jul 6 21:24:51 2019 +0100 Fix recent regression in __atomic_add_dispatch * include/ext/atomicity.h (__exchange_and_add, __atomic_add): Replace throw() with _GLIBCXX_NOTHROW. (__atomic_add_dispatch): Return after performing atomic increment. diff --git a/libstdc++-v3/include/ext/atomicity.h b/libstdc++-v3/include/ext/atomicity.h index 73225b3de20..333c8843e14 100644 --- a/libstdc++-v3/include/ext/atomicity.h +++ b/libstdc++-v3/include/ext/atomicity.h @@ -55,10 +55,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { __atomic_fetch_add(__mem, __val, __ATOMIC_ACQ_REL); } #else _Atomic_word - __exchange_and_add(volatile _Atomic_word*, int) throw (); + __exchange_and_add(volatile _Atomic_word*, int) _GLIBCXX_NOTHROW; void - __atomic_add(volatile _Atomic_word*, int) throw (); + __atomic_add(volatile _Atomic_word*, int) _GLIBCXX_NOTHROW; #endif inline _Atomic_word @@ -92,7 +92,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { #ifdef __GTHREADS if (__gthread_active_p()) - __atomic_add(__mem, __val); + { + __atomic_add(__mem, __val); + return; + } #endif __atomic_add_single(__mem, __val); }
Re: [PATCH] Fix ODR violations in code using
On 05/07/19 20:23 +0200, Daniel Krügler wrote: Am Fr., 5. Juli 2019 um 18:13 Uhr schrieb Jonathan Wakely : [..] I decided against the simplification in the second patch, and committed the attached one which is closer to the first patch I sent (preserving the __atomic_add and __exchange_and_add functions even when they just call the built-ins). Tested x86_64-linux, powerpc64-linux, powerpc-aix. Committed to trunk. Unrelated to the actual patch, I noticed some explicit "throw()" forms used as exception specifications - shouldn't these be replaced by either explicit "noexcept" or at least by a library macro that expands to one or the other? Yes, they should be _GLIBCXX_NOTHROW. (I'm sorry, if such unrelated questions are considered as inappropriate for this list). Entirely appropriate, thanks!
Re: [PATCH] Fix ODR violations in code using
Am Fr., 5. Juli 2019 um 18:13 Uhr schrieb Jonathan Wakely : > [..] > I decided against the simplification in the second patch, and > committed the attached one which is closer to the first patch I sent > (preserving the __atomic_add and __exchange_and_add functions even > when they just call the built-ins). > > Tested x86_64-linux, powerpc64-linux, powerpc-aix. Committed to trunk. Unrelated to the actual patch, I noticed some explicit "throw()" forms used as exception specifications - shouldn't these be replaced by either explicit "noexcept" or at least by a library macro that expands to one or the other? (I'm sorry, if such unrelated questions are considered as inappropriate for this list). - Daniel
Re: [PATCH] Fix ODR violations in code using
On 21/06/19 18:13 +0100, Jonathan Wakely wrote: On 21/06/19 18:08 +0100, Jonathan Wakely wrote: On 21/06/19 13:01 -0400, Nathan Sidwell wrote: On 6/21/19 12:01 PM, Jonathan Wakely wrote: Nathan noticed that the 'static inline' functions in cause ODR violations when used from inline functions or templates (see [basic.def.odr] p12 bullet (12.2)). His modules branch now diagnoses those violations, so we need a fix. Looking at the history (r114044 by Paolo) I believe the idea was indeed to allow different definitions to be used in different TUs. I think __attribute__((__always_inline__)) is a better match for that than 'static inline', and doesn't violate the ODR (at least, not if all TUs have the same values for __GTHREADS and _GLIBCXX_ATOMIC_BUILTINS). These functions still violate this rule in [dcl.inline]: C++17: "If a function with external linkage is declared inline in one translation unit, it shall be declared inline in all translation units in which it appears; no diagnostic is required." C++2a WP: "If a function or variable with external or module linkage is declared inline in one translation unit, there shall be a reachable inline declaration in all translation units in which it is declared; no diagnostic is required." But that doesn't seem to be diagnosable by today's implementations. Does this change seem reasonable? yes, thanks! Actually, I think I prefer this version. This produces identical code to the always_inline version, but without the indirection to additional inline functions, i.e. just inline the relevant code into the _dispatch functions. Tests are still running but no failures so far, as expected. Oops, I spoke too soon: FAIL: tr1/2_general_utilities/shared_ptr/thread/default_weaktoshared.cc (test for excess errors) UNRESOLVED: tr1/2_general_utilities/shared_ptr/thread/default_weaktoshared.cc compilation failed to produce executable FAIL: tr1/2_general_utilities/shared_ptr/thread/mutex_weaktoshared.cc (test for excess errors) UNRESOLVED: tr1/2_general_utilities/shared_ptr/thread/mutex_weaktoshared.cc compilation failed to produce executable Those tests explicitly use the __atomic_add function that the patch removes. But those would be easy to adjust. I decided against the simplification in the second patch, and committed the attached one which is closer to the first patch I sent (preserving the __atomic_add and __exchange_and_add functions even when they just call the built-ins). Tested x86_64-linux, powerpc64-linux, powerpc-aix. Committed to trunk. commit 0d26b6506f20dcb1c956338baba0c26f623e25f2 Author: Jonathan Wakely Date: Fri Jul 5 15:15:46 2019 +0100 Fix ODR violations in code using Because the inline versions of __exchange_and_add and __atomic_add are also marked static, they cannot be used from templates or other inline functions without ODR violations. This change gives them external linkage, but adds the always_inline attribute. * include/ext/atomicity.h [_GLIBCXX_ATOMIC_BUILTINS] (__atomic_add) (__exchange_and_add): Replace static specifier with always_inline attribute. (__exchange_and_add_single, __atomic_add_single): Likewise. (__exchange_and_add_dispatch, __atomic_add_dispatch): Likewise. Also combine !__gthread_active_p() and !__GTHREADS branches. diff --git a/libstdc++-v3/include/ext/atomicity.h b/libstdc++-v3/include/ext/atomicity.h index 0783a58e01a..73225b3de20 100644 --- a/libstdc++-v3/include/ext/atomicity.h +++ b/libstdc++-v3/include/ext/atomicity.h @@ -44,24 +44,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // __exchange_and_add_dispatch // __atomic_add_dispatch #ifdef _GLIBCXX_ATOMIC_BUILTINS - static inline _Atomic_word + inline _Atomic_word + __attribute__((__always_inline__)) __exchange_and_add(volatile _Atomic_word* __mem, int __val) { return __atomic_fetch_add(__mem, __val, __ATOMIC_ACQ_REL); } - static inline void + inline void + __attribute__((__always_inline__)) __atomic_add(volatile _Atomic_word* __mem, int __val) { __atomic_fetch_add(__mem, __val, __ATOMIC_ACQ_REL); } #else _Atomic_word - __attribute__ ((__unused__)) __exchange_and_add(volatile _Atomic_word*, int) throw (); void - __attribute__ ((__unused__)) __atomic_add(volatile _Atomic_word*, int) throw (); #endif - static inline _Atomic_word + inline _Atomic_word + __attribute__((__always_inline__)) __exchange_and_add_single(_Atomic_word* __mem, int __val) { _Atomic_word __result = *__mem; @@ -69,36 +70,31 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __result; } - static inline void + inline void + __attribute__((__always_inline__)) __atomic_add_single(_Atomic_word* __mem, int __val) { *__mem += __val; } - static inline _Atomic_word - __attribute__ ((__unused__)) + inline _Atomic_word + __attribute__ ((__always_inline__)) __exchange_and_add_dispatch(_Atomic_word* __mem, int __val)
Re: [PATCH] Fix ODR violations in code using
On 21/06/19 18:08 +0100, Jonathan Wakely wrote: On 21/06/19 13:01 -0400, Nathan Sidwell wrote: On 6/21/19 12:01 PM, Jonathan Wakely wrote: Nathan noticed that the 'static inline' functions in cause ODR violations when used from inline functions or templates (see [basic.def.odr] p12 bullet (12.2)). His modules branch now diagnoses those violations, so we need a fix. Looking at the history (r114044 by Paolo) I believe the idea was indeed to allow different definitions to be used in different TUs. I think __attribute__((__always_inline__)) is a better match for that than 'static inline', and doesn't violate the ODR (at least, not if all TUs have the same values for __GTHREADS and _GLIBCXX_ATOMIC_BUILTINS). These functions still violate this rule in [dcl.inline]: C++17: "If a function with external linkage is declared inline in one translation unit, it shall be declared inline in all translation units in which it appears; no diagnostic is required." C++2a WP: "If a function or variable with external or module linkage is declared inline in one translation unit, there shall be a reachable inline declaration in all translation units in which it is declared; no diagnostic is required." But that doesn't seem to be diagnosable by today's implementations. Does this change seem reasonable? yes, thanks! Actually, I think I prefer this version. This produces identical code to the always_inline version, but without the indirection to additional inline functions, i.e. just inline the relevant code into the _dispatch functions. Tests are still running but no failures so far, as expected. Oops, I spoke too soon: FAIL: tr1/2_general_utilities/shared_ptr/thread/default_weaktoshared.cc (test for excess errors) UNRESOLVED: tr1/2_general_utilities/shared_ptr/thread/default_weaktoshared.cc compilation failed to produce executable FAIL: tr1/2_general_utilities/shared_ptr/thread/mutex_weaktoshared.cc (test for excess errors) UNRESOLVED: tr1/2_general_utilities/shared_ptr/thread/mutex_weaktoshared.cc compilation failed to produce executable Those tests explicitly use the __atomic_add function that the patch removes. But those would be easy to adjust.
Re: [PATCH] Fix ODR violations in code using
On 21/06/19 13:01 -0400, Nathan Sidwell wrote: On 6/21/19 12:01 PM, Jonathan Wakely wrote: Nathan noticed that the 'static inline' functions in cause ODR violations when used from inline functions or templates (see [basic.def.odr] p12 bullet (12.2)). His modules branch now diagnoses those violations, so we need a fix. Looking at the history (r114044 by Paolo) I believe the idea was indeed to allow different definitions to be used in different TUs. I think __attribute__((__always_inline__)) is a better match for that than 'static inline', and doesn't violate the ODR (at least, not if all TUs have the same values for __GTHREADS and _GLIBCXX_ATOMIC_BUILTINS). These functions still violate this rule in [dcl.inline]: C++17: "If a function with external linkage is declared inline in one translation unit, it shall be declared inline in all translation units in which it appears; no diagnostic is required." C++2a WP: "If a function or variable with external or module linkage is declared inline in one translation unit, there shall be a reachable inline declaration in all translation units in which it is declared; no diagnostic is required." But that doesn't seem to be diagnosable by today's implementations. Does this change seem reasonable? yes, thanks! Actually, I think I prefer this version. This produces identical code to the always_inline version, but without the indirection to additional inline functions, i.e. just inline the relevant code into the _dispatch functions. Tests are still running but no failures so far, as expected. commit 56040dad3b55a98f6e5090d04cb49945c40df39c Author: Jonathan Wakely Date: Fri Jun 21 17:52:23 2019 +0100 Simplify diff --git a/libstdc++-v3/include/ext/atomicity.h b/libstdc++-v3/include/ext/atomicity.h index 0783a58e01a..30453c92315 100644 --- a/libstdc++-v3/include/ext/atomicity.h +++ b/libstdc++-v3/include/ext/atomicity.h @@ -43,62 +43,49 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // To abstract locking primitives across all thread policies, use: // __exchange_and_add_dispatch // __atomic_add_dispatch -#ifdef _GLIBCXX_ATOMIC_BUILTINS - static inline _Atomic_word - __exchange_and_add(volatile _Atomic_word* __mem, int __val) - { return __atomic_fetch_add(__mem, __val, __ATOMIC_ACQ_REL); } - - static inline void - __atomic_add(volatile _Atomic_word* __mem, int __val) - { __atomic_fetch_add(__mem, __val, __ATOMIC_ACQ_REL); } -#else +#ifndef _GLIBCXX_ATOMIC_BUILTINS _Atomic_word - __attribute__ ((__unused__)) __exchange_and_add(volatile _Atomic_word*, int) throw (); void - __attribute__ ((__unused__)) __atomic_add(volatile _Atomic_word*, int) throw (); #endif - static inline _Atomic_word - __exchange_and_add_single(_Atomic_word* __mem, int __val) + inline _Atomic_word + __attribute__ ((__always_inline__)) + __exchange_and_add_dispatch(_Atomic_word* __mem, int __val) { +#ifdef __GTHREADS +if (__gthread_active_p()) + { +#ifdef _GLIBCXX_ATOMIC_BUILTINS + return __atomic_fetch_add(__mem, __val, __ATOMIC_ACQ_REL); +#else + return __exchange_and_add(__mem, __val); +#endif + } +#endif _Atomic_word __result = *__mem; *__mem += __val; return __result; } - static inline void - __atomic_add_single(_Atomic_word* __mem, int __val) - { *__mem += __val; } - - static inline _Atomic_word - __attribute__ ((__unused__)) - __exchange_and_add_dispatch(_Atomic_word* __mem, int __val) - { -#ifdef __GTHREADS -if (__gthread_active_p()) - return __exchange_and_add(__mem, __val); -else - return __exchange_and_add_single(__mem, __val); -#else -return __exchange_and_add_single(__mem, __val); -#endif - } - - static inline void - __attribute__ ((__unused__)) + inline void + __attribute__ ((__always_inline__)) __atomic_add_dispatch(_Atomic_word* __mem, int __val) { #ifdef __GTHREADS if (__gthread_active_p()) - __atomic_add(__mem, __val); -else - __atomic_add_single(__mem, __val); + { +#ifdef _GLIBCXX_ATOMIC_BUILTINS + __atomic_fetch_add(__mem, __val, __ATOMIC_ACQ_REL); #else -__atomic_add_single(__mem, __val); + __atomic_add(__mem, __val); #endif + } +else +#endif +*__mem += __val; } _GLIBCXX_END_NAMESPACE_VERSION diff --git a/libstdc++-v3/src/c++98/mt_allocator.cc b/libstdc++-v3/src/c++98/mt_allocator.cc index f842c6f9cfd..9b26f3dc993 100644 --- a/libstdc++-v3/src/c++98/mt_allocator.cc +++ b/libstdc++-v3/src/c++98/mt_allocator.cc @@ -302,7 +302,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION if (__reclaimed > 1024) { __bin._M_used[__thread_id] -= __reclaimed; - __atomic_add(&__reclaimed_base[__thread_id], -__reclaimed); + __atomic_fetch_add(&__reclaimed_base[__thread_id], -__reclaimed, + __ATOMIC_ACQ_REL); } if (__remove >= __net_used) @@ -332,7 +333,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION if (__block->_M_thread_id == __thread_id) --__bin._M_used[__thread_id]; else -
Re: [PATCH] Fix ODR violations in code using
On 6/21/19 12:01 PM, Jonathan Wakely wrote: Nathan noticed that the 'static inline' functions in cause ODR violations when used from inline functions or templates (see [basic.def.odr] p12 bullet (12.2)). His modules branch now diagnoses those violations, so we need a fix. Looking at the history (r114044 by Paolo) I believe the idea was indeed to allow different definitions to be used in different TUs. I think __attribute__((__always_inline__)) is a better match for that than 'static inline', and doesn't violate the ODR (at least, not if all TUs have the same values for __GTHREADS and _GLIBCXX_ATOMIC_BUILTINS). These functions still violate this rule in [dcl.inline]: C++17: "If a function with external linkage is declared inline in one translation unit, it shall be declared inline in all translation units in which it appears; no diagnostic is required." C++2a WP: "If a function or variable with external or module linkage is declared inline in one translation unit, there shall be a reachable inline declaration in all translation units in which it is declared; no diagnostic is required." But that doesn't seem to be diagnosable by today's implementations. Does this change seem reasonable? yes, thanks! nathan -- Nathan Sidwell
[PATCH] Fix ODR violations in code using
Nathan noticed that the 'static inline' functions in cause ODR violations when used from inline functions or templates (see [basic.def.odr] p12 bullet (12.2)). His modules branch now diagnoses those violations, so we need a fix. Looking at the history (r114044 by Paolo) I believe the idea was indeed to allow different definitions to be used in different TUs. I think __attribute__((__always_inline__)) is a better match for that than 'static inline', and doesn't violate the ODR (at least, not if all TUs have the same values for __GTHREADS and _GLIBCXX_ATOMIC_BUILTINS). These functions still violate this rule in [dcl.inline]: C++17: "If a function with external linkage is declared inline in one translation unit, it shall be declared inline in all translation units in which it appears; no diagnostic is required." C++2a WP: "If a function or variable with external or module linkage is declared inline in one translation unit, there shall be a reachable inline declaration in all translation units in which it is declared; no diagnostic is required." But that doesn't seem to be diagnosable by today's implementations. Does this change seem reasonable? It does change the size of a few files, e.g. for x86_64 some are bigger and some are smaller, overall slightly smaller: text data bss dec hex filename 54008 35257601680 src/c++11/cow-locale_init.o 54028 35257621682 src/c++11/cow-locale_init.o [always_inline] 22772 2056 0 2482860fc src/c++11/cow-shim_facets.o 22710 2056 0 2476660be src/c++11/cow-shim_facets.o [always_inline] 49458 2184 0 51642c9ba src/c++11/cow-sstream-inst.o 49482 2184 0 51666c9d2 src/c++11/cow-sstream-inst.o [always_inline] 74618 074691d2d src/c++11/cow-stdexcept.o 74648 074721d30 src/c++11/cow-stdexcept.o [always_inline] 167538 32 167934199 src/c++11/cow-string-inst.o 167568 32 16796419c src/c++11/cow-string-inst.o [always_inline] 170098 32 170494299 src/c++11/cow-wstring-inst.o 170088 32 170484298 src/c++11/cow-wstring-inst.o [always_inline] 20342 2072 0 22414578e src/c++11/cxx11-shim_facets.o 20276 2072 0 22348574c src/c++11/cxx11-shim_facets.o [always_inline] 2929 240 83177 c69 src/c++11/future.o 2945 240 83193 c79 src/c++11/future.o [always_inline] 6789 120 069091afd src/c++11/ios-inst.o 6750 120 068701ad6 src/c++11/ios-inst.o [always_inline] 2364 57 82429 97d src/c++11/ios.o 2362 57 82427 97b src/c++11/ios.o [always_inline] 94493 2712 192 97397 17c75 src/c++11/locale-inst.o 94498 2712 192 97402 17c7a src/c++11/locale-inst.o [always_inline] 93094 2712 192 95998 176fe src/c++11/wlocale-inst.o 93113 2712 192 96017 17711 src/c++11/wlocale-inst.o [always_inline] 20189 208 0 203974fad src/c++17/cow-fs_dir.o 20118 208 0 203264f66 src/c++17/cow-fs_dir.o [always_inline] 550778 0 55085d72d src/c++17/cow-fs_ops.o 551038 0 55111d747 src/c++17/cow-fs_ops.o [always_inline] 40200 304 0 405049e38 src/c++17/cow-fs_path.o 40204 304 0 405089e3c src/c++17/cow-fs_path.o [always_inline] 18672 208 0 1888049c0 src/c++17/fs_dir.o 18628 208 0 188364994 src/c++17/fs_dir.o [always_inline] 60604 160 0 60764ed5c src/c++17/fs_ops.o 60606 160 0 60766ed5e src/c++17/fs_ops.o [always_inline] 39568 304 0 398729bc0 src/c++17/fs_path.o 39561 304 0 398659bb9 src/c++17/fs_path.o [always_inline] 36538 03661 e4d src/c++98/ios_init.o 36568 03664 e50 src/c++98/ios_init.o [always_inline] 6878 184 8471461bea src/c++98/locale.o 6896 184 8471641bfc src/c++98/locale.o [always_inline] 6693 7685368 12829321d src/c++98/locale_init.o 6710 7685368 12846322e src/c++98/locale_init.o [always_inline] 72228 072301c3e src/c++98/localename.o 72238 072311c3f src/c++98/localename.o [always_inline] 4036 144 20843881124 src/c++98/pool_allocator.o 4044 144 2084396112c src/c++98/pool_allocator.o [always_inline] 1955 584 02539 9eb src/c++98/stdexcept.o 1957 584 02541 9ed src/c++98/stdexcept.o [always_inline] 25199 208 0 25407633f src/filesystem/cow-dir.o 25248 208 0 254566370 src/filesystem/cow-dir.o [always_inline] 711348 0 71142 115e6