[libcxx-commits] [libcxxabi] 847ea76 - [libcxxabi] Pulled guard byte code out of GuardObject
Daniel McIntosh via libcxx-commits
libcxx-commits at lists.llvm.org
Wed Jan 12 14:30:43 PST 2022
Author: Daniel McIntosh
Date: 2022-01-12T17:30:39-05:00
New Revision: 847ea76219899961a7af6d675c0d5512f9a33dea
URL: https://github.com/llvm/llvm-project/commit/847ea76219899961a7af6d675c0d5512f9a33dea
DIFF: https://github.com/llvm/llvm-project/commit/847ea76219899961a7af6d675c0d5512f9a33dea.diff
LOG: [libcxxabi] Pulled guard byte code out of GuardObject
Right now, GuardObject is in charge of both reading and writing to the guard
byte, and co-ordinating with the InitByte... classes. In order to improve
separation of concerns, create a separate class responsible for managing the
guard byte and use that inside GuardObject.
This is the 3rd of 5 changes to overhaul cxa_guard.
See D108343 for what the final result will be.
Depends on D110088
Reviewed By: ldionne, #libc_abi
Differential Revision: https://reviews.llvm.org/D115367
Added:
Modified:
libcxxabi/src/cxa_guard_impl.h
Removed:
################################################################################
diff --git a/libcxxabi/src/cxa_guard_impl.h b/libcxxabi/src/cxa_guard_impl.h
index d431050ca3a86..36477e4da4f01 100644
--- a/libcxxabi/src/cxa_guard_impl.h
+++ b/libcxxabi/src/cxa_guard_impl.h
@@ -156,6 +156,46 @@ uint32_t PlatformThreadID() {
constexpr uint32_t (*PlatformThreadID)() = nullptr;
#endif
+//===----------------------------------------------------------------------===//
+// GuardByte
+//===----------------------------------------------------------------------===//
+
+static constexpr uint8_t UNSET = 0;
+static constexpr uint8_t COMPLETE_BIT = (1 << 0);
+static constexpr uint8_t PENDING_BIT = (1 << 1);
+static constexpr uint8_t WAITING_BIT = (1 << 2);
+
+/// Manages reads and writes to the guard byte.
+struct GuardByte {
+ GuardByte() = delete;
+ GuardByte(GuardByte const&) = delete;
+ GuardByte& operator=(GuardByte const&) = delete;
+
+ explicit GuardByte(uint8_t* const guard_byte_address) : guard_byte(guard_byte_address) {}
+
+public:
+ /// The guard byte portion of cxa_guard_acquire. Returns true if
+ /// initialization has already been completed.
+ /// Note: On completion, we haven't 'acquired' ownership of anything mutex
+ /// related. The name is simply referring to __cxa_guard_acquire.
+ bool acquire() {
+ // if guard_byte is non-zero, we have already completed initialization
+ // (i.e. release has been called)
+ return guard_byte.load(std::_AO_Acquire) != UNSET;
+ }
+
+ /// The guard byte portion of cxa_guard_release.
+ /// Note: On completion, we haven't 'released' ownership of anything mutex
+ /// related. The name is simply referring to __cxa_guard_release.
+ void release() { guard_byte.store(COMPLETE_BIT, std::_AO_Release); }
+
+ /// The guard byte portion of cxa_guard_abort.
+ void abort() {} // Nothing to do
+
+private:
+ AtomicInt<uint8_t> guard_byte;
+};
+
//===----------------------------------------------------------------------===//
// GuardBase
//===----------------------------------------------------------------------===//
@@ -167,51 +207,51 @@ enum class AcquireResult {
constexpr AcquireResult INIT_IS_DONE = AcquireResult::INIT_IS_DONE;
constexpr AcquireResult INIT_IS_PENDING = AcquireResult::INIT_IS_PENDING;
-static constexpr uint8_t UNSET = 0;
-static constexpr uint8_t COMPLETE_BIT = (1 << 0);
-static constexpr uint8_t PENDING_BIT = (1 << 1);
-static constexpr uint8_t WAITING_BIT = (1 << 2);
-
template <class Derived>
struct GuardObject {
GuardObject() = delete;
GuardObject(GuardObject const&) = delete;
GuardObject& operator=(GuardObject const&) = delete;
+private:
+ GuardByte guard_byte;
+
+public:
+ /// ARM Constructor
explicit GuardObject(uint32_t* g)
- : base_address(g), guard_byte_address(reinterpret_cast<uint8_t*>(g)),
+ : guard_byte(reinterpret_cast<uint8_t*>(g)), base_address(g),
init_byte_address(reinterpret_cast<uint8_t*>(g) + 1), thread_id_address(nullptr) {}
+ /// Itanium Constructor
explicit GuardObject(uint64_t* g)
- : base_address(g), guard_byte_address(reinterpret_cast<uint8_t*>(g)),
+ : guard_byte(reinterpret_cast<uint8_t*>(g)), base_address(g),
init_byte_address(reinterpret_cast<uint8_t*>(g) + 1), thread_id_address(reinterpret_cast<uint32_t*>(g) + 1) {}
-public:
- /// Implements __cxa_guard_acquire
+ /// Implements __cxa_guard_acquire.
AcquireResult cxa_guard_acquire() {
- AtomicInt<uint8_t> guard_byte(guard_byte_address);
- if (guard_byte.load(std::_AO_Acquire) != UNSET)
+ if (guard_byte.acquire())
return INIT_IS_DONE;
return derived()->acquire_init_byte();
}
- /// Implements __cxa_guard_release
+ /// Implements __cxa_guard_release.
void cxa_guard_release() {
- AtomicInt<uint8_t> guard_byte(guard_byte_address);
- // Store complete first, so that when release wakes other folks, they see
- // it as having been completed.
- guard_byte.store(COMPLETE_BIT, std::_AO_Release);
+ // Update guard byte first, so if somebody is woken up by release_init_byte
+ // and comes all the way back around to __cxa_guard_acquire again, they see
+ // it as having completed initialization.
+ guard_byte.release();
derived()->release_init_byte();
}
- /// Implements __cxa_guard_abort
- void cxa_guard_abort() { derived()->abort_init_byte(); }
+ /// Implements __cxa_guard_abort.
+ void cxa_guard_abort() {
+ guard_byte.abort();
+ derived()->abort_init_byte();
+ }
public:
/// base_address - the address of the original guard object.
void* const base_address;
- /// The address of the guard byte at offset 0.
- uint8_t* const guard_byte_address;
/// The address of the byte used by the implementation during initialization.
uint8_t* const init_byte_address;
/// An optional address storing an identifier for the thread performing initialization.
More information about the libcxx-commits
mailing list