From d91119ba78692f92876f95d2a6adf93a71930446 Mon Sep 17 00:00:00 2001 From: Sergey Bugaev Date: Tue, 6 Jul 2021 15:28:19 +0300 Subject: [PATCH] test-pthread: Add semaphore tests --- Userland/Utilities/test-pthread.cpp | 106 ++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) diff --git a/Userland/Utilities/test-pthread.cpp b/Userland/Utilities/test-pthread.cpp index 559ece4a46..b1684dc795 100644 --- a/Userland/Utilities/test-pthread.cpp +++ b/Userland/Utilities/test-pthread.cpp @@ -7,7 +7,9 @@ #include #include #include +#include #include +#include #include static void test_once() @@ -34,8 +36,112 @@ static void test_once() VERIFY(v.size() == 1); } +static void test_semaphore_as_lock() +{ + constexpr size_t threads_count = 10; + constexpr size_t num_times = 100; + + Vector v; + NonnullRefPtrVector threads; + sem_t semaphore; + sem_init(&semaphore, 0, 1); + + for (size_t i = 0; i < threads_count; i++) { + threads.append(Threading::Thread::construct([&] { + for (size_t j = 0; j < num_times; j++) { + sem_wait(&semaphore); + v.append(35); + sched_yield(); + sem_post(&semaphore); + sched_yield(); + } + return 0; + })); + threads.last().start(); + } + for (auto& thread : threads) + [[maybe_unused]] auto res = thread.join(); + + VERIFY(v.size() == threads_count * num_times); + VERIFY(sem_trywait(&semaphore) == 0); + VERIFY(sem_trywait(&semaphore) == EAGAIN); +} + +static void test_semaphore_as_event() +{ + Vector v; + sem_t semaphore; + sem_init(&semaphore, 0, 0); + + auto reader = Threading::Thread::construct([&] { + sem_wait(&semaphore); + VERIFY(v.size() == 1); + return 0; + }); + reader->start(); + + auto writer = Threading::Thread::construct([&] { + sched_yield(); + v.append(35); + sem_post(&semaphore); + return 0; + }); + writer->start(); + + [[maybe_unused]] auto r1 = reader->join(); + [[maybe_unused]] auto r2 = writer->join(); + + VERIFY(sem_trywait(&semaphore) == EAGAIN); +} + +static void test_semaphore_nonbinary() +{ + constexpr size_t num = 5; + constexpr size_t threads_count = 10; + constexpr size_t num_times = 100; + + NonnullRefPtrVector threads; + sem_t semaphore; + sem_init(&semaphore, 0, num); + + Atomic value = 0; + Atomic seen_more_than_two = false; + + for (size_t i = 0; i < threads_count; i++) { + threads.append(Threading::Thread::construct([&] { + for (size_t j = 0; j < num_times; j++) { + sem_wait(&semaphore); + u32 v = 1 + value.fetch_add(1); + VERIFY(v <= num); + if (v > 2) + seen_more_than_two.store(true); + sched_yield(); + value.fetch_sub(1); + sem_post(&semaphore); + } + return 0; + })); + threads.last().start(); + } + + for (auto& thread : threads) + [[maybe_unused]] auto res = thread.join(); + + VERIFY(value.load() == 0); + VERIFY(seen_more_than_two.load()); + for (size_t i = 0; i < num; i++) { + VERIFY(sem_trywait(&semaphore) == 0); + } + VERIFY(sem_trywait(&semaphore) == EAGAIN); +} + int main() { test_once(); + + test_semaphore_as_lock(); + test_semaphore_as_event(); + test_semaphore_nonbinary(); + return 0; }