diff options
| author | Felix Morgner <felix.morgner@ost.ch> | 2026-07-26 23:44:11 +0200 |
|---|---|---|
| committer | Felix Morgner <felix.morgner@ost.ch> | 2026-07-26 23:44:11 +0200 |
| commit | 724e7698dc2795cf96f07ba16a078abd4e93cb46 (patch) | |
| tree | 94ef9c43c1a5baf3459bbc239e603cafea76e627 | |
| parent | 8ea14be48c3fce44add60533904a77ccc80138f7 (diff) | |
| download | kernel-724e7698dc2795cf96f07ba16a078abd4e93cb46.tar.xz kernel-724e7698dc2795cf96f07ba16a078abd4e93cb46.zip | |
kapi/bus: extend stress tests
| -rw-r--r-- | kernel/kapi/devices/bus.stress.cpp | 81 |
1 files changed, 79 insertions, 2 deletions
diff --git a/kernel/kapi/devices/bus.stress.cpp b/kernel/kapi/devices/bus.stress.cpp index 3fefc892..507650f0 100644 --- a/kernel/kapi/devices/bus.stress.cpp +++ b/kernel/kapi/devices/bus.stress.cpp @@ -7,6 +7,7 @@ #include <atomic> #include <cstddef> +#include <mutex> #include <thread> #include <tuple> #include <vector> @@ -21,8 +22,8 @@ namespace } // namespace -constexpr auto thread_count = 8; -constexpr auto devices_per_thread = 200; +constexpr auto thread_count = 8uz; +constexpr auto devices_per_thread = 200uz; SCENARIO("Concurrent attach/detach/lookup on a bus is race-free") { @@ -73,4 +74,80 @@ SCENARIO("Concurrent attach/detach/lookup on a bus is race-free") } } } +} + +SCENARIO("Concurrent removal of a bus with its own children is race-free") +{ + GIVEN("A shared parent bus, and a pool of child busses attached to it") + { + auto parent_bus = kstd::make_shared<kapi::devices::bus>("stress_test_nested_parent"); + kapi::devices::get_root_bus()->add_child(parent_bus); + + constexpr auto pool_size = 8uz; + + auto pool_lock = std::mutex{}; + auto pool = std::vector<kstd::shared_ptr<kapi::devices::bus>>{}; + + for (auto i = 0uz; i < pool_size; ++i) + { + auto child = kstd::make_shared<kapi::devices::bus>(kstd::format("stress_test_nested_child_{}", i)); + parent_bus->add_child(child); + pool.push_back(child); + } + + WHEN("threads concurrently attach devices to shared child busses, while others tear an entire child bus down " + "through the parent and replace it") + { + auto threads = std::vector<std::jthread>{}; + threads.reserve(thread_count); + + auto failures = std::atomic<std::size_t>{0}; + + for (auto thread_index = 0uz; thread_index < thread_count; ++thread_index) + { + threads.emplace_back([&pool, &pool_lock, &parent_bus, &failures, thread_index] { + for (auto i = 0uz; i < devices_per_thread; ++i) + { + auto pool_index = (thread_index + i) % pool_size; + + auto child_bus = kstd::shared_ptr<kapi::devices::bus>{}; + { + auto guard = std::lock_guard{pool_lock}; + child_bus = pool[pool_index]; + } + + auto name = kstd::format("stress_test_nested_device_{}_{}", thread_index, i); + auto device = kstd::make_shared<test_device>(name); + + child_bus->add_child(device); + + if (!child_bus->remove_child(*device)) + { + ++failures; + } + + if (i % 25 == 0) + { + if (parent_bus->remove_child(*child_bus)) + { + auto replacement = + kstd::make_shared<kapi::devices::bus>(kstd::format("stress_test_nested_child_{}", pool_index)); + parent_bus->add_child(replacement); + + auto guard = std::lock_guard{pool_lock}; + pool[pool_index] = replacement; + } + } + } + }); + } + + threads.clear(); + + THEN("every direct attach to a child bus was matched by a successful removal") + { + REQUIRE(failures == 0); + } + } + } }
\ No newline at end of file |
