Commit bbd6fb43 authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook Github Bot

No mutable flags in IOBuf

Summary: [Folly] No mutable flags in IOBuf to avoid races when invoking `const`-qualified members concurrently.

Reviewed By: simpkins

Differential Revision: D17251909

fbshipit-source-id: e52d333fb620d05f7229a11db9c2f14fe9f6f028
parent b1233937
...@@ -591,7 +591,6 @@ IOBuf IOBuf::cloneAsValue() const { ...@@ -591,7 +591,6 @@ IOBuf IOBuf::cloneAsValue() const {
IOBuf IOBuf::cloneOneAsValue() const { IOBuf IOBuf::cloneOneAsValue() const {
if (SharedInfo* info = sharedInfo()) { if (SharedInfo* info = sharedInfo()) {
setFlags(kFlagMaybeShared);
info->refcount.fetch_add(1, std::memory_order_acq_rel); info->refcount.fetch_add(1, std::memory_order_acq_rel);
} }
return IOBuf( return IOBuf(
...@@ -657,7 +656,7 @@ void IOBuf::unshareOneSlow() { ...@@ -657,7 +656,7 @@ void IOBuf::unshareOneSlow() {
// Release our reference on the old buffer // Release our reference on the old buffer
decrementRefcount(); decrementRefcount();
// Make sure kFlagMaybeShared and kFlagFreeSharedInfo are all cleared. // Make sure flags are all cleared.
setFlagsAndSharedInfo(0, sharedInfo); setFlagsAndSharedInfo(0, sharedInfo);
// Update the buffer pointers to point to the new buffer // Update the buffer pointers to point to the new buffer
...@@ -790,7 +789,7 @@ void IOBuf::coalesceAndReallocate( ...@@ -790,7 +789,7 @@ void IOBuf::coalesceAndReallocate(
// Point at the new buffer // Point at the new buffer
decrementRefcount(); decrementRefcount();
// Make sure kFlagMaybeShared and kFlagFreeSharedInfo are all cleared. // Make sure flags are all cleared.
setFlagsAndSharedInfo(0, newInfo); setFlagsAndSharedInfo(0, newInfo);
capacity_ = actualCapacity; capacity_ = actualCapacity;
...@@ -1176,15 +1175,7 @@ uint32_t IOBuf::approximateShareCountOne() const { ...@@ -1176,15 +1175,7 @@ uint32_t IOBuf::approximateShareCountOne() const {
if (UNLIKELY(!sharedInfo())) { if (UNLIKELY(!sharedInfo())) {
return 1U; return 1U;
} }
if (LIKELY(!(flags() & kFlagMaybeShared))) { return sharedInfo()->refcount.load(std::memory_order_acquire);
return 1U;
}
auto shareCount = sharedInfo()->refcount.load(std::memory_order_acquire);
if (shareCount < 2) {
// we're the last one left
clearFlags(kFlagMaybeShared);
}
return shareCount;
} }
size_t IOBufHash::operator()(const IOBuf& buf) const noexcept { size_t IOBufHash::operator()(const IOBuf& buf) const noexcept {
......
...@@ -1020,19 +1020,7 @@ class IOBuf { ...@@ -1020,19 +1020,7 @@ class IOBuf {
return true; return true;
} }
if (LIKELY(!(flags() & kFlagMaybeShared))) { return sharedInfo()->refcount.load(std::memory_order_acquire) > 1;
return false;
}
// kFlagMaybeShared is set, so we need to check the reference count.
// (Checking the reference count requires an atomic operation, which is why
// we prefer to only check kFlagMaybeShared if possible.)
bool shared = sharedInfo()->refcount.load(std::memory_order_acquire) > 1;
if (!shared) {
// we're the last one left
clearFlags(kFlagMaybeShared);
}
return shared;
} }
/** /**
...@@ -1409,8 +1397,7 @@ class IOBuf { ...@@ -1409,8 +1397,7 @@ class IOBuf {
// as these flags are stashed in the least significant 2 bits of a // as these flags are stashed in the least significant 2 bits of a
// max-align-aligned pointer. // max-align-aligned pointer.
kFlagFreeSharedInfo = 0x1, kFlagFreeSharedInfo = 0x1,
kFlagMaybeShared = 0x2, kFlagMask = (1 << 2 /* least significant bits */) - 1,
kFlagMask = kFlagFreeSharedInfo | kFlagMaybeShared
}; };
struct SharedInfoObserverEntryBase { struct SharedInfoObserverEntryBase {
...@@ -1541,7 +1528,7 @@ class IOBuf { ...@@ -1541,7 +1528,7 @@ class IOBuf {
std::size_t capacity_{0}; std::size_t capacity_{0};
// Pack flags in least significant 2 bits, sharedInfo in the rest // Pack flags in least significant 2 bits, sharedInfo in the rest
mutable uintptr_t flagsAndSharedInfo_{0}; uintptr_t flagsAndSharedInfo_{0};
static inline uintptr_t packFlagsAndSharedInfo( static inline uintptr_t packFlagsAndSharedInfo(
uintptr_t flags, uintptr_t flags,
...@@ -1567,12 +1554,12 @@ class IOBuf { ...@@ -1567,12 +1554,12 @@ class IOBuf {
} }
// flags_ are changed from const methods // flags_ are changed from const methods
inline void setFlags(uintptr_t flags) const noexcept { inline void setFlags(uintptr_t flags) noexcept {
DCHECK_EQ(flags & ~kFlagMask, 0u); DCHECK_EQ(flags & ~kFlagMask, 0u);
flagsAndSharedInfo_ |= flags; flagsAndSharedInfo_ |= flags;
} }
inline void clearFlags(uintptr_t flags) const noexcept { inline void clearFlags(uintptr_t flags) noexcept {
DCHECK_EQ(flags & ~kFlagMask, 0u); DCHECK_EQ(flags & ~kFlagMask, 0u);
flagsAndSharedInfo_ &= ~flags; flagsAndSharedInfo_ &= ~flags;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment