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:
Alan Jowett 2024-01-11 11:24:15 -08:00 коммит произвёл GitHub
Родитель a2ece4ba26
Коммит 5556190460
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
1 изменённых файлов: 63 добавлений и 18 удалений

Просмотреть файл

@ -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.