4 ms·
Related to this, GNU's libstdc++ shared_ptr implementation actually opts not to use atomic arithmetic when it infers that the program is not using threads.
by eMSF 1y ago
Related to this, GNU's libstdc++ shared_ptr implementation actually opts not to use atomic arithmetic when it infers that the program is not using threads.
- menaerus 1y agoI never heard of this and went to check in the source and it really does exist: https://codebrowser.dev/llvm/include/c++/11/ext/concurrence.h.html#__gnu_cxx::__default_lock_policy https://codebrowser.dev/llvm/include/c++/11/ext/concurrence....
- aw1621107 1y agoThe code you linked is a compile-time configuration option, which doesn't quite match "infer" IMO. I think GP is thinking of the way that libstdc++ basically relies on the linker to tell it whether libpthread is linked in and skips atomic operations if it isn't [0]. [0]: https://snf.github.io/2019/02/13/shared-ptr-optimization/ https://snf.github.io/2019/02/13/shared-ptr-optimization/
- menaerus 1y agoIt's a compile-time flag which is defined when libpthread is linked into the binary.
- aw1621107 1y agoSure, but I think that's independent of what eMSF was describing. From libgcc/gthr.h: /* If this file is compiled with threads support, it must #define __GTHREADS 1 to indicate that threads support is present. Also it has define function int __gthread_active_p () that returns 1 if thread system is active, 0 if not. I think the mechanism eMSF was describing (and the mechanism in the blogpost I linked) corresponds to __gthread_active_p(). I think the distinction between the two should be visible in some cases - for example, what happens for shared libraries that use std::shared_ptr and don't link libpthread, but are later used with a binary that does link libpthread?
- menaerus 1y agoHm, not sure. I can see that shared_ptr::_M_release [0] is implemented in terms of __exchange_and_add_dispatch [1] and which is implemented in terms of __is_single_threaded [2]. __is_single_threaded will use __gthread_active_p iff __GTHREADS is not defined and <sys/single_threaded.h> header not included. Implementation of __gthread_active_p is indeed a runtime check [3] which AFAICS applies only to single-threaded programs. Perhaps the shared-library use-case also fits here? Strange optimization IMHO so I wonder what was the motivation behind it. The cost function being optimized in this case is depending on WORD being atomic [4] without actually using the atomics [5]. [0] https://codebrowser.dev/llvm/include/c++/11/bits/shared_ptr_base.h.html#165 https://codebrowser.dev/llvm/include/c++/11/bits/shared_ptr_... [1] https://codebrowser.dev/llvm/include/c++/11/ext/atomicity.h.html#98 https://codebrowser.dev/llvm/include/c++/11/ext/atomicity.h.... [2] https://codebrowser.dev/llvm/include/c++/11/ext/atomicity.h.html#47 https://codebrowser.dev/llvm/include/c++/11/ext/atomicity.h.... [3] https://codebrowser.dev/kde/include/x86_64-linux-gnu/c++/11/bits/gthr-default.h.html#181 https://codebrowser.dev/kde/include/x86_64-linux-gnu/c++/11/... [4] https://codebrowser.dev/llvm/include/c++/11/ext/atomicity.h.html#84 https://codebrowser.dev/llvm/include/c++/11/ext/atomicity.h.... [5] https://codebrowser.dev/llvm/include/c++/11/ext/atomicity.h.html#66 https://codebrowser.dev/llvm/include/c++/11/ext/atomicity.h....
- aw1621107 1y ago> Implementation of __gthread_active_p is indeed a runtime check [3] which AFAICS applies only to single-threaded programs. Perhaps the shared-library use-case also fits here? The line you linked is for some FreeBSD/Solaris versions which appear to have some quirks with the way pthreads functions are exposed in their libc. I think the "normal" implementation of __gthread_active_p is on line 248 [0], and that is a pretty straightforwards check against a weak symbol. > Strange optimization IMHO so I wonder what was the motivation behind it. I believe the motivation is to avoid needing to pay the cost of atomics when there is no parallelism going on. > The cost function being optimized in this case is depending on WORD being atomic [4] without actually using the atomics [5]. Not entirely sure what you're getting at here? The former is used for single-threaded programs so there's ostensibly no need for atomics, whereas the latter is used for non-single-threaded programs. [0]: https://codebrowser.dev/kde/include/x86_64-linux-gnu/c++/11/bits/gthr-default.h.html#248 https://codebrowser.dev/kde/include/x86_64-linux-gnu/c++/11/...