Add RAII wrapper for epoch_enter/exit (#3167)
Signed-off-by: Alan Jowett <alan.jowett@microsoft.com> Co-authored-by: Alan Jowett <alan.jowett@microsoft.com>
This commit is contained in:
Родитель
a2ece4ba26
Коммит
5556190460
|
@ -146,6 +146,59 @@ struct ebpf_hash_table_destroyer_t
|
||||||
|
|
||||||
using ebpf_hash_table_ptr = std::unique_ptr<ebpf_hash_table_t, ebpf_hash_table_destroyer_t>;
|
using ebpf_hash_table_ptr = std::unique_ptr<ebpf_hash_table_t, ebpf_hash_table_destroyer_t>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A RAII class to enter and exit epoch.
|
||||||
|
*/
|
||||||
|
typedef class _ebpf_epoch_scope
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Construct a new ebpf epoch scope object and enter epoch.
|
||||||
|
*/
|
||||||
|
_ebpf_epoch_scope() : in_epoch(false) { enter(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Leave epoch if entered.
|
||||||
|
*/
|
||||||
|
~_ebpf_epoch_scope()
|
||||||
|
{
|
||||||
|
if (in_epoch) {
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Enter epoch.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
enter()
|
||||||
|
{
|
||||||
|
if (in_epoch) {
|
||||||
|
throw std::runtime_error("Already in epoch.");
|
||||||
|
}
|
||||||
|
memset(&epoch_state, 0, sizeof(epoch_state));
|
||||||
|
ebpf_epoch_enter(&epoch_state);
|
||||||
|
in_epoch = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Exit epoch.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
exit()
|
||||||
|
{
|
||||||
|
if (!in_epoch) {
|
||||||
|
throw std::runtime_error("Not in epoch.");
|
||||||
|
}
|
||||||
|
ebpf_epoch_exit(&epoch_state);
|
||||||
|
in_epoch = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
ebpf_epoch_state_t epoch_state;
|
||||||
|
bool in_epoch;
|
||||||
|
} ebpf_epoch_scope_t;
|
||||||
|
|
||||||
TEST_CASE("hash_table_test", "[platform]")
|
TEST_CASE("hash_table_test", "[platform]")
|
||||||
{
|
{
|
||||||
std::vector<uint8_t> key_1(13);
|
std::vector<uint8_t> key_1(13);
|
||||||
|
@ -309,10 +362,8 @@ TEST_CASE("hash_table_test", "[platform]")
|
||||||
void
|
void
|
||||||
run_in_epoch(std::function<void()> function)
|
run_in_epoch(std::function<void()> function)
|
||||||
{
|
{
|
||||||
ebpf_epoch_state_t epoch_state = {0};
|
ebpf_epoch_scope_t epoch_scope;
|
||||||
ebpf_epoch_enter(&epoch_state);
|
|
||||||
function();
|
function();
|
||||||
ebpf_epoch_exit(&epoch_state);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("hash_table_stress_test", "[platform]")
|
TEST_CASE("hash_table_stress_test", "[platform]")
|
||||||
|
@ -471,11 +522,10 @@ TEST_CASE("epoch_test_single_epoch", "[platform]")
|
||||||
_test_helper test_helper;
|
_test_helper test_helper;
|
||||||
test_helper.initialize();
|
test_helper.initialize();
|
||||||
|
|
||||||
ebpf_epoch_state_t epoch_state;
|
ebpf_epoch_scope_t epoch_scope;
|
||||||
ebpf_epoch_enter(&epoch_state);
|
|
||||||
void* memory = ebpf_epoch_allocate(10);
|
void* memory = ebpf_epoch_allocate(10);
|
||||||
ebpf_epoch_free(memory);
|
ebpf_epoch_free(memory);
|
||||||
ebpf_epoch_exit(&epoch_state);
|
epoch_scope.exit();
|
||||||
ebpf_epoch_synchronize();
|
ebpf_epoch_synchronize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -485,13 +535,12 @@ TEST_CASE("epoch_test_two_threads", "[platform]")
|
||||||
test_helper.initialize();
|
test_helper.initialize();
|
||||||
|
|
||||||
auto epoch = []() {
|
auto epoch = []() {
|
||||||
ebpf_epoch_state_t epoch_state;
|
ebpf_epoch_scope_t epoch_scope;
|
||||||
ebpf_epoch_enter(&epoch_state);
|
|
||||||
void* memory = ebpf_epoch_allocate(10);
|
void* memory = ebpf_epoch_allocate(10);
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||||
|
|
||||||
ebpf_epoch_free(memory);
|
ebpf_epoch_free(memory);
|
||||||
ebpf_epoch_exit(&epoch_state);
|
epoch_scope.exit();
|
||||||
ebpf_epoch_synchronize();
|
ebpf_epoch_synchronize();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -524,23 +573,21 @@ TEST_CASE("epoch_test_stale_items", "[platform]")
|
||||||
auto t1 = [&]() {
|
auto t1 = [&]() {
|
||||||
uintptr_t old_thread_affinity;
|
uintptr_t old_thread_affinity;
|
||||||
ebpf_assert_success(ebpf_set_current_thread_affinity(1, &old_thread_affinity));
|
ebpf_assert_success(ebpf_set_current_thread_affinity(1, &old_thread_affinity));
|
||||||
ebpf_epoch_state_t epoch_state;
|
ebpf_epoch_scope_t epoch_scope;
|
||||||
ebpf_epoch_enter(&epoch_state);
|
|
||||||
void* memory = ebpf_epoch_allocate(10);
|
void* memory = ebpf_epoch_allocate(10);
|
||||||
signal_2.signal();
|
signal_2.signal();
|
||||||
signal_1.wait();
|
signal_1.wait();
|
||||||
ebpf_epoch_free(memory);
|
ebpf_epoch_free(memory);
|
||||||
ebpf_epoch_exit(&epoch_state);
|
epoch_scope.exit();
|
||||||
};
|
};
|
||||||
auto t2 = [&]() {
|
auto t2 = [&]() {
|
||||||
uintptr_t old_thread_affinity;
|
uintptr_t old_thread_affinity;
|
||||||
ebpf_assert_success(ebpf_set_current_thread_affinity(2, &old_thread_affinity));
|
ebpf_assert_success(ebpf_set_current_thread_affinity(2, &old_thread_affinity));
|
||||||
signal_2.wait();
|
signal_2.wait();
|
||||||
ebpf_epoch_state_t epoch_state;
|
ebpf_epoch_scope_t epoch_scope;
|
||||||
ebpf_epoch_enter(&epoch_state);
|
|
||||||
void* memory = ebpf_epoch_allocate(10);
|
void* memory = ebpf_epoch_allocate(10);
|
||||||
ebpf_epoch_free(memory);
|
ebpf_epoch_free(memory);
|
||||||
ebpf_epoch_exit(&epoch_state);
|
epoch_scope.exit();
|
||||||
signal_1.signal();
|
signal_1.signal();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -909,8 +956,7 @@ TEST_CASE("async", "[platform]")
|
||||||
test_helper.initialize();
|
test_helper.initialize();
|
||||||
|
|
||||||
auto test = [](bool complete) {
|
auto test = [](bool complete) {
|
||||||
ebpf_epoch_state_t epoch_state;
|
ebpf_epoch_scope_t epoch_scope;
|
||||||
ebpf_epoch_enter(&epoch_state);
|
|
||||||
struct _async_context
|
struct _async_context
|
||||||
{
|
{
|
||||||
ebpf_result_t result;
|
ebpf_result_t result;
|
||||||
|
@ -947,7 +993,6 @@ TEST_CASE("async", "[platform]")
|
||||||
REQUIRE(cancellation_context.canceled);
|
REQUIRE(cancellation_context.canceled);
|
||||||
ebpf_async_complete(&async_context, 0, EBPF_SUCCESS);
|
ebpf_async_complete(&async_context, 0, EBPF_SUCCESS);
|
||||||
}
|
}
|
||||||
ebpf_epoch_exit(&epoch_state);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Run the test with complete before cancel.
|
// Run the test with complete before cancel.
|
||||||
|
|
Загрузка…
Ссылка в новой задаче