1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-14 09:04:59 +00:00

test-pthread: Add semaphore tests

This commit is contained in:
Sergey Bugaev 2021-07-06 15:28:19 +03:00 committed by Andreas Kling
parent 5aa629717e
commit d91119ba78

View file

@ -7,7 +7,9 @@
#include <AK/Assertions.h>
#include <AK/NonnullRefPtrVector.h>
#include <LibThreading/Thread.h>
#include <errno.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
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<int> v;
NonnullRefPtrVector<Threading::Thread, threads_count> 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<int> 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<Threading::Thread, threads_count> threads;
sem_t semaphore;
sem_init(&semaphore, 0, num);
Atomic<u32, AK::memory_order_relaxed> value = 0;
Atomic<bool, AK::memory_order_relaxed> 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;
}