8#include "pedigree/kernel/Atomic.h"
9#include "pedigree/kernel/Log.h"
10#include "pedigree/kernel/process/Scheduler.h"
11#include "pedigree/kernel/process/Semaphore.h"
12#include "pedigree/kernel/process/Thread.h"
13#include "pedigree/kernel/time/Time.h"
15#include "modules/subsys/posix/UnixFilesystem.h"
18bool check(
bool condition,
const char* test,
const char* detail) {
23 ERROR(
"HOSTED-WAIT-TEST: FAIL " << test <<
": " << detail);
27bool waitUntilQueued(
Thread* thread) {
28 const Time::Timestamp deadline = Time::getTicks() + (500 * Time::Multiplier::Millisecond);
29 while (Time::getTicks() < deadline) {
31 uintptr_t debugAddress = 0;
41struct PollWaitContext {
42 explicit PollWaitContext(
Semaphore* readiness) : readiness(readiness), entered(0), woke(0) {}
49int waitForPollReadiness(
void* parameter) {
50 PollWaitContext* context =
reinterpret_cast<PollWaitContext*
>(parameter);
51 context->entered += 1;
52 if (context->readiness->acquireForCompletion()) {
58Thread* startPollWaiter(PollWaitContext& context,
const char* name) {
60 &context,
nullptr,
false,
true);
65bool datagramPollSendWake() {
66 UnixSocket socket(
String(),
nullptr,
nullptr,
nullptr, UnixSocket::Datagram);
68 socket.addWaiter(&readiness,
true,
false);
70 PollWaitContext context(&readiness);
71 Thread*
waiter = startPollWaiter(context,
"hosted Unix datagram send poll");
72 const bool queued = waitUntilQueued(
waiter);
75 const bool wrote = socket.writeBytewise(0,
sizeof(sent),
reinterpret_cast<uintptr_t
>(&sent),
76 false) ==
sizeof(sent);
77 const bool joined =
waiter->join();
81 const bool read = socket.recvfrom(
sizeof(received),
reinterpret_cast<uintptr_t
>(&received),
false,
82 from) ==
sizeof(received);
84 const bool passed = check(
85 context.entered == 1 && queued && wrote && joined && context.woke == 1 && read &&
86 received == sent && !readiness.tryAcquire(),
87 "unix-datagram-poll-send",
"a datagram did not wake exactly the waiter enrolled on its ring");
89 NOTICE(
"HOSTED-WAIT-TEST: PASS unix-datagram-poll-send");
94bool datagramPollCloseWake() {
95 UnixSocket socket(
String(),
nullptr,
nullptr,
nullptr, UnixSocket::Datagram);
97 socket.addWaiter(&readiness,
true,
false);
99 PollWaitContext context(&readiness);
100 Thread*
waiter = startPollWaiter(context,
"hosted Unix datagram close poll");
101 const bool queued = waitUntilQueued(
waiter);
104 const bool joined =
waiter->join();
107 socket.addWaiter(&lateReadiness,
true,
false);
109 const bool passed = check(
110 context.entered == 1 && queued && joined && context.woke == 1 &&
111 socket.getState() == UnixSocket::Closed && socket.select(
false, 0) &&
112 !socket.select(
true, 0) && !readiness.tryAcquire() && lateReadiness.tryAcquire(),
113 "unix-datagram-poll-close",
"datagram close did not wake poll with persistent EOF readiness");
115 NOTICE(
"HOSTED-WAIT-TEST: PASS unix-datagram-poll-close");
120bool streamPollCloseWake() {
121 UnixSocket local(
String(),
nullptr,
nullptr,
nullptr, UnixSocket::Streaming);
122 UnixSocket peer(
String(),
nullptr,
nullptr,
nullptr, UnixSocket::Streaming);
123 const bool connected = local.bind(&peer);
124 peer.acknowledgeBind();
127 local.addWaiter(&readiness,
true,
false);
129 PollWaitContext context(&readiness);
130 Thread*
waiter = startPollWaiter(context,
"hosted Unix stream close poll");
131 const bool queued = waitUntilQueued(
waiter);
134 const bool joined =
waiter->join();
137 local.addWaiter(&lateReadiness,
true,
false);
139 const bool passed = check(
140 connected && context.entered == 1 && queued && joined && context.woke == 1 &&
141 local.getState() == UnixSocket::Closed && local.select(
false, 0) &&
142 !local.select(
true, 0) && !readiness.tryAcquire() && lateReadiness.tryAcquire() &&
143 !lateReadiness.tryAcquire(),
144 "unix-stream-poll-close",
"stream close did not wake poll with persistent EOF readiness");
146 NOTICE(
"HOSTED-WAIT-TEST: PASS unix-stream-poll-close");
152EXPORTED_PUBLIC
bool runHostedUnixDatagramRegressions() {
153 return datagramPollSendWake() && datagramPollCloseWake() && streamPollCloseWake();
static Scheduler & instance()
bool getWaitDebugInfo(WaitDebugInfo &info)
DebugState getDebugState(uintptr_t &address)