Use of C++ dynamic global object initialization with thread guards
Kim Barrett
kim.barrett at oracle.com
Wed Dec 6 09:21:15 UTC 2023
> On Dec 4, 2023, at 2:28 AM, Florian Weimer <fweimer at redhat.com> wrote:
>
> As far as I understand it, the Hotspot C++ style guide advises not use
> C++ run-time library features.
Largely true.
> However, it seems that the use of
> dynamic initialization guards (that involve calls to __cxa_guard_acquire
> and __cxa_guard_release) has increased quite a bit over the years.
Also true. We weren’t supposed to be using that at all before adopting C++11/14,
which defined function scoped static initialization to be thread safe. But now that
we have that feature, we’re allowed to use it, and it’s sometimes/often better than
hand-rolled alternatives, at least as far as source code simplicity and readability.
> The implementation of __cxa_guard_acquire is not entirely trivial
> because it detects recursive initialization and throws
> __gnu_cxx::recursive_init_error, which means that it pulls in the C++
> unwinder (at least with a traditional GNU/Linux build of libstdc++.a).
Does it? Seems like it shouldn’t. We build with -fno-exceptions, and the definition
of throw_recursive_init_exception is conditionalized on __cpp_exceptions, only
throwing when that macro is defined. It calls __builtin_trap() if that macro isn’t
defined.
And that’s the sort of thing I expected to find. For something from the runtime library
to throw when under the influence of -fno-exceptions seems like a bug.
> Furthermore, most uses of C++ dynamic initialization involve a
> computation that is idempotent and have unused bit patterns in the
> initialized value. This means that a separate guard variable is not
> needed, and a simple atomic store/atomic load could be used.
That’s the kind of complexity we’d really rather avoid if possible.
> In other cases, the use of global objects seems unnecessary. For
> example, src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp
> has a dynamically initialized static variable max_elem_size:
>
> [… code snipped …]
> The min_element_size() member function is inline and just returns
> _min_element_size, which is declared const, so it cannot change over
> time. This means that caching that value is pointless, and the static
> should probably removed.
I agree this seems like an inappropriate use of static. It only works here because
the manager object being referenced is a singleton.
> Would it make sense to minimize the use of __cxa_guard_acquire and
> __cxa_guard_release? There are currently 400 such calls, but many of
> them appear in templated code, so I could get it down to ~80 calls with
> about a days of work.
I don’t think so, since I currently don’t think the described problem (pulling in
exception unwinding) actually exists.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: Message signed with OpenPGP
URL: <https://mail.openjdk.org/pipermail/hotspot-dev/attachments/20231206/7fbdd8e5/signature-0001.asc>
More information about the hotspot-dev
mailing list