aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp
diff options
context:
space:
mode:
authorrobot-piglet <robot-piglet@yandex-team.com>2023-05-29 13:44:19 +0300
committerrobot-piglet <robot-piglet@yandex-team.com>2023-05-29 13:44:19 +0300
commit341da7ab23a5b193c5e632f8a1e6d9d7042221b1 (patch)
treef451174a5f088f220beee4da727d2ec1c6cc29ce /library/cpp
parent48333f6d85dd05e428bbea51030c458cb29e302a (diff)
downloadydb-341da7ab23a5b193c5e632f8a1e6d9d7042221b1.tar.gz
Intermediate changes
Diffstat (limited to 'library/cpp')
-rw-r--r--library/cpp/ytalloc/impl/core-inl.h98
1 files changed, 8 insertions, 90 deletions
diff --git a/library/cpp/ytalloc/impl/core-inl.h b/library/cpp/ytalloc/impl/core-inl.h
index babf58aaa8..c02a983a2c 100644
--- a/library/cpp/ytalloc/impl/core-inl.h
+++ b/library/cpp/ytalloc/impl/core-inl.h
@@ -12,6 +12,8 @@
#include <library/cpp/yt/threading/at_fork.h>
#include <library/cpp/yt/threading/fork_aware_spin_lock.h>
+#include <library/cpp/yt/memory/free_list.h>
+
#include <util/system/tls.h>
#include <util/system/align.h>
#include <util/system/thread.h>
@@ -505,89 +507,6 @@ Y_FORCE_INLINE void PoisonUninitializedRange(void* ptr, size_t size)
////////////////////////////////////////////////////////////////////////////////
-template <class T>
-struct TFreeListItem
-{
- T* Next = nullptr;
-};
-
-constexpr size_t CacheLineSize = 64;
-
-// A lock-free stack of items (derived from TFreeListItem).
-// Supports multiple producers and multiple consumers.
-// Internally uses DCAS with tagged pointers to defeat ABA.
-template <class T>
-class TFreeList
-{
-public:
- void Put(T* item)
- {
- TTaggedPointer currentTaggedHead{};
- TTaggedPointer newTaggedHead;
- do {
- item->Next = currentTaggedHead.first;
- newTaggedHead = std::make_pair(item, currentTaggedHead.second + 1);
- } while (!CompareAndSet(&TaggedHead_, currentTaggedHead, newTaggedHead));
- }
-
- T* Extract()
- {
- T* item;
- TTaggedPointer currentTaggedHead{};
- TTaggedPointer newTaggedHead{};
- CompareAndSet(&TaggedHead_, currentTaggedHead, newTaggedHead);
- do {
- item = currentTaggedHead.first;
- if (!item) {
- break;
- }
- newTaggedHead = std::make_pair(item->Next, currentTaggedHead.second + 1);
- } while (!CompareAndSet(&TaggedHead_, currentTaggedHead, newTaggedHead));
- return item;
- }
-
- T* ExtractAll()
- {
- T* item;
- TTaggedPointer currentTaggedHead{};
- TTaggedPointer newTaggedHead;
- do {
- item = currentTaggedHead.first;
- newTaggedHead = std::make_pair(nullptr, currentTaggedHead.second + 1);
- } while (!CompareAndSet(&TaggedHead_, currentTaggedHead, newTaggedHead));
- return item;
- }
-
-private:
- using TAtomicUint128 = volatile unsigned __int128 __attribute__((aligned(16)));
- using TTag = ui64;
- using TTaggedPointer = std::pair<T*, TTag>;
-
- TAtomicUint128 TaggedHead_ = 0;
-
- // Avoid false sharing.
- char Padding[CacheLineSize - sizeof(TAtomicUint128)];
-
-private:
- static Y_FORCE_INLINE bool CompareAndSet(TAtomicUint128* atomic, TTaggedPointer& expectedValue, TTaggedPointer newValue)
- {
- bool success;
- __asm__ __volatile__
- (
- "lock cmpxchg16b %1\n"
- "setz %0"
- : "=q"(success)
- , "+m"(*atomic)
- , "+a"(expectedValue.first)
- , "+d"(expectedValue.second)
- : "b"(newValue.first)
- , "c"(newValue.second)
- : "cc"
- );
- return success;
- }
-};
-
static_assert(sizeof(TFreeList<void>) == CacheLineSize, "sizeof(TFreeList) != CacheLineSize");
////////////////////////////////////////////////////////////////////////////////
@@ -1747,7 +1666,7 @@ TExplicitlyConstructableSingleton<TMmapObservationManager> MmapObservationManage
// A per-thread structure containing counters, chunk caches etc.
struct TThreadState
- : public TFreeListItem<TThreadState>
+ : public TFreeListItemBase<TThreadState>
, public TLocalShardedState
{
// TThreadState instances of all alive threads are put into a double-linked intrusive list.
@@ -2917,7 +2836,7 @@ constexpr size_t GroupsBatchSize = 1024;
static_assert(ChunksPerGroup <= MaxCachedChunksPerRank, "ChunksPerGroup > MaxCachedChunksPerRank");
class TChunkGroup
- : public TFreeListItem<TChunkGroup>
+ : public TFreeListItemBase<TChunkGroup>
{
public:
bool IsEmpty() const
@@ -3449,7 +3368,7 @@ enum ELargeBlobState : ui64
// Every large blob (either tagged or not) is prepended with this header.
struct TLargeBlobHeader
- : public TFreeListItem<TLargeBlobHeader>
+ : public TFreeListItemBase<TLargeBlobHeader>
{
TLargeBlobHeader(
TLargeBlobExtent* extent,
@@ -3494,7 +3413,7 @@ struct TLargeBlobExtent
// A helper node that enables storing a number of extent's segments
// in a free list. Recall that segments themselves do not posses any headers.
struct TDisposedSegment
- : public TFreeListItem<TDisposedSegment>
+ : public TFreeListItemBase<TDisposedSegment>
{
size_t Index;
TLargeBlobExtent* Extent;
@@ -3656,7 +3575,7 @@ private:
size_t count = 0;
while (blob) {
- auto* nextBlob = blob->Next;
+ auto* nextBlob = blob->Next.load();
YTALLOC_VERIFY(!blob->Locked.load());
AssertBlobState(blob, ELargeBlobState::LockedSpare);
blob->State = ELargeBlobState::Spare;
@@ -3679,7 +3598,7 @@ private:
size_t count = 0;
while (blob) {
- auto* nextBlob = blob->Next;
+ auto* nextBlob = blob->Next.load();
AssertBlobState(blob, ELargeBlobState::LockedFreed);
MoveBlobToSpare(state, arena, blob, false);
++count;
@@ -4928,4 +4847,3 @@ TEnumIndexedVector<ETimingEventType, TTimingEventCounters> GetTimingEventCounter
////////////////////////////////////////////////////////////////////////////////
} // namespace NYT::NYTAlloc
-