forked from llvm/llvm-project
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[scudo] Add ConditionVariable in SizeClassAllocator64 (llvm#69031)
This may improve the waiting of `Region->MMLock` while trying to refill the freelist. Instead of always waiting on the completion of `populateFreeListAndPopBatch()` or `releaseToOSMaybe()`, `pushBlocks()` also refills the freelist. This increases the chance of earlier return from `popBatches()`. The support of condition variable hasn't been done for all platforms. Therefore, add another `popBatchWithCV()` and it can be configured in the allocator configuration by setting `Primary::UseConditionVariable` and the desired `ConditionVariableT`. Reviewed By: cferris Differential Revision: https://reviews.llvm.org/D156146
- Loading branch information
1 parent
ff21a90
commit ab17ecd
Showing
11 changed files
with
476 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
//===-- condition_variable.h ------------------------------------*- C++ -*-===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef SCUDO_CONDITION_VARIABLE_H_ | ||
#define SCUDO_CONDITION_VARIABLE_H_ | ||
|
||
#include "condition_variable_base.h" | ||
|
||
#include "common.h" | ||
#include "platform.h" | ||
|
||
#include "condition_variable_linux.h" | ||
|
||
namespace scudo { | ||
|
||
// A default implementation of default condition variable. It doesn't do a real | ||
// `wait`, instead it spins a short amount of time only. | ||
class ConditionVariableDummy | ||
: public ConditionVariableBase<ConditionVariableDummy> { | ||
public: | ||
void notifyAllImpl(UNUSED HybridMutex &M) REQUIRES(M) {} | ||
|
||
void waitImpl(UNUSED HybridMutex &M) REQUIRES(M) { | ||
M.unlock(); | ||
|
||
constexpr u32 SpinTimes = 64; | ||
volatile u32 V = 0; | ||
for (u32 I = 0; I < SpinTimes; ++I) { | ||
u32 Tmp = V + 1; | ||
V = Tmp; | ||
} | ||
|
||
M.lock(); | ||
} | ||
}; | ||
|
||
template <typename Config, typename = const bool> | ||
struct ConditionVariableState { | ||
static constexpr bool enabled() { return false; } | ||
// This is only used for compilation purpose so that we won't end up having | ||
// many conditional compilations. If you want to use `ConditionVariableDummy`, | ||
// define `ConditionVariableT` in your allocator configuration. See | ||
// allocator_config.h for more details. | ||
using ConditionVariableT = ConditionVariableDummy; | ||
}; | ||
|
||
template <typename Config> | ||
struct ConditionVariableState<Config, decltype(Config::UseConditionVariable)> { | ||
static constexpr bool enabled() { return true; } | ||
using ConditionVariableT = typename Config::ConditionVariableT; | ||
}; | ||
|
||
} // namespace scudo | ||
|
||
#endif // SCUDO_CONDITION_VARIABLE_H_ |
56 changes: 56 additions & 0 deletions
56
compiler-rt/lib/scudo/standalone/condition_variable_base.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
//===-- condition_variable_base.h -------------------------------*- C++ -*-===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef SCUDO_CONDITION_VARIABLE_BASE_H_ | ||
#define SCUDO_CONDITION_VARIABLE_BASE_H_ | ||
|
||
#include "mutex.h" | ||
#include "thread_annotations.h" | ||
|
||
namespace scudo { | ||
|
||
template <typename Derived> class ConditionVariableBase { | ||
public: | ||
constexpr ConditionVariableBase() = default; | ||
|
||
void bindTestOnly(HybridMutex &Mutex) { | ||
#if SCUDO_DEBUG | ||
boundMutex = &Mutex; | ||
#else | ||
(void)Mutex; | ||
#endif | ||
} | ||
|
||
void notifyAll(HybridMutex &M) REQUIRES(M) { | ||
#if SCUDO_DEBUG | ||
CHECK_EQ(&M, boundMutex); | ||
#endif | ||
getDerived()->notifyAllImpl(M); | ||
} | ||
|
||
void wait(HybridMutex &M) REQUIRES(M) { | ||
#if SCUDO_DEBUG | ||
CHECK_EQ(&M, boundMutex); | ||
#endif | ||
getDerived()->waitImpl(M); | ||
} | ||
|
||
protected: | ||
Derived *getDerived() { return static_cast<Derived *>(this); } | ||
|
||
#if SCUDO_DEBUG | ||
// Because thread-safety analysis doesn't support pointer aliasing, we are not | ||
// able to mark the proper annotations without false positive. Instead, we | ||
// pass the lock and do the same-lock check separately. | ||
HybridMutex *boundMutex = nullptr; | ||
#endif | ||
}; | ||
|
||
} // namespace scudo | ||
|
||
#endif // SCUDO_CONDITION_VARIABLE_BASE_H_ |
52 changes: 52 additions & 0 deletions
52
compiler-rt/lib/scudo/standalone/condition_variable_linux.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
//===-- condition_variable_linux.cpp ----------------------------*- C++ -*-===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#include "platform.h" | ||
|
||
#if SCUDO_LINUX | ||
|
||
#include "condition_variable_linux.h" | ||
|
||
#include "atomic_helpers.h" | ||
|
||
#include <limits.h> | ||
#include <linux/futex.h> | ||
#include <sys/syscall.h> | ||
#include <unistd.h> | ||
|
||
namespace scudo { | ||
|
||
void ConditionVariableLinux::notifyAllImpl(UNUSED HybridMutex &M) { | ||
const u32 V = atomic_load_relaxed(&Counter); | ||
atomic_store_relaxed(&Counter, V + 1); | ||
|
||
// TODO(chiahungduan): Move the waiters from the futex waiting queue | ||
// `Counter` to futex waiting queue `M` so that the awoken threads won't be | ||
// blocked again due to locked `M` by current thread. | ||
if (LastNotifyAll != V) { | ||
syscall(SYS_futex, reinterpret_cast<uptr>(&Counter), FUTEX_WAKE_PRIVATE, | ||
INT_MAX, nullptr, nullptr, 0); | ||
} | ||
|
||
LastNotifyAll = V + 1; | ||
} | ||
|
||
void ConditionVariableLinux::waitImpl(HybridMutex &M) { | ||
const u32 V = atomic_load_relaxed(&Counter) + 1; | ||
atomic_store_relaxed(&Counter, V); | ||
|
||
// TODO: Use ScopedUnlock when it's supported. | ||
M.unlock(); | ||
syscall(SYS_futex, reinterpret_cast<uptr>(&Counter), FUTEX_WAIT_PRIVATE, V, | ||
nullptr, nullptr, 0); | ||
M.lock(); | ||
} | ||
|
||
} // namespace scudo | ||
|
||
#endif // SCUDO_LINUX |
38 changes: 38 additions & 0 deletions
38
compiler-rt/lib/scudo/standalone/condition_variable_linux.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
//===-- condition_variable_linux.h ------------------------------*- C++ -*-===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef SCUDO_CONDITION_VARIABLE_LINUX_H_ | ||
#define SCUDO_CONDITION_VARIABLE_LINUX_H_ | ||
|
||
#include "platform.h" | ||
|
||
#if SCUDO_LINUX | ||
|
||
#include "atomic_helpers.h" | ||
#include "condition_variable_base.h" | ||
#include "thread_annotations.h" | ||
|
||
namespace scudo { | ||
|
||
class ConditionVariableLinux | ||
: public ConditionVariableBase<ConditionVariableLinux> { | ||
public: | ||
void notifyAllImpl(HybridMutex &M) REQUIRES(M); | ||
|
||
void waitImpl(HybridMutex &M) REQUIRES(M); | ||
|
||
private: | ||
u32 LastNotifyAll = 0; | ||
atomic_u32 Counter = {}; | ||
}; | ||
|
||
} // namespace scudo | ||
|
||
#endif // SCUDO_LINUX | ||
|
||
#endif // SCUDO_CONDITION_VARIABLE_LINUX_H_ |
Oops, something went wrong.