The Pedigree Project 0.1
hosted-smoke/syscall-regressions.cc
1/*
2 * Copyright (c) 2026, Pedigree Developers
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted.
6 */
7
8#include "pedigree/kernel/Atomic.h"
9#include "pedigree/kernel/Log.h"
10#include "pedigree/kernel/process/PerProcessorScheduler.h"
11#include "pedigree/kernel/process/Scheduler.h"
12#include "pedigree/kernel/process/TerminationDeferral.h"
13#include "pedigree/kernel/process/Thread.h"
14#include "pedigree/kernel/process/Uninterruptible.h"
15#include "pedigree/kernel/processor/Processor.h"
16#include "pedigree/kernel/processor/SyscallHandler.h"
17#include "pedigree/kernel/processor/SyscallManager.h"
18#include "pedigree/kernel/processor/state.h"
19#include "pedigree/kernel/time/Time.h"
20#include "pedigree/kernel/utilities/utility.h"
21
22namespace {
23bool check(bool condition, const char* test, const char* detail) {
24 if (condition) {
25 return true;
26 }
27
28 ERROR("HOSTED-WAIT-TEST: FAIL " << test << ": " << detail);
29 return false;
30}
31
32struct HandlerLifetimeContext;
33HandlerLifetimeContext* g_HandlerLifetimeContext = nullptr;
34
35class LifetimeHandler : public SyscallHandler {
36 public:
37 explicit LifetimeHandler(HandlerLifetimeContext& context) : m_Context(context) {}
38
39 uintptr_t syscall(SyscallState&) override;
40
41 private:
42 HandlerLifetimeContext& m_Context;
43};
44
45struct HandlerLifetimeContext {
46 HandlerLifetimeContext()
47 : handler(*this),
48 remover(nullptr),
49 phase(0),
50 hookCalls(0),
51 hookObservedDrain(0),
52 handlerCalls(0),
53 callbacksAfterReturn(0),
54 unregisterReturned(0),
55 unregisterSucceeded(0),
56 failures(0) {}
57
58 LifetimeHandler handler;
60 Thread* remover;
61 Atomic<size_t> phase;
62 Atomic<size_t> hookCalls;
63 Atomic<size_t> hookObservedDrain;
64 Atomic<size_t> handlerCalls;
65 Atomic<size_t> callbacksAfterReturn;
66 Atomic<size_t> unregisterReturned;
67 Atomic<size_t> unregisterSucceeded;
68 Atomic<size_t> failures;
69};
70
71uintptr_t LifetimeHandler::syscall(SyscallState&) {
72 m_Context.handlerCalls += 1;
73 if (m_Context.unregisterReturned) {
74 m_Context.callbacksAfterReturn += 1;
75 }
76 return 0x51;
77}
78
79class SelfUnregisteringHandler : public SyscallHandler {
80 public:
81 explicit SelfUnregisteringHandler(SyscallManager::Registration& registration)
82 : m_Registration(registration), calls(0), rejectionSeen(0) {}
83
84 uintptr_t syscall(SyscallState&) override {
85 calls += 1;
86 if (!m_Registration.reset() && m_Registration) {
87 rejectionSeen += 1;
88 }
89 return 0x52;
90 }
91
92 SyscallManager::Registration& m_Registration;
93 Atomic<size_t> calls;
94 Atomic<size_t> rejectionSeen;
95};
96
97struct ReciprocalUnregisterContext;
98
99class ReciprocalUnregisterHandler : public SyscallHandler {
100 public:
101 ReciprocalUnregisterHandler(ReciprocalUnregisterContext& context, bool first)
102 : m_Context(context), m_First(first) {}
103
104 uintptr_t syscall(SyscallState&) override;
105
106 private:
107 ReciprocalUnregisterContext& m_Context;
108 bool m_First;
109};
110
111struct ReciprocalUnregisterContext {
112 ReciprocalUnregisterContext()
113 : first(*this, true),
114 second(*this, false),
115 entered(0),
116 attempts(0),
117 rejections(0),
118 resetReturns(0),
119 failures(0) {}
120
121 ReciprocalUnregisterHandler first;
122 ReciprocalUnregisterHandler second;
123 SyscallManager::Registration firstRegistration;
124 SyscallManager::Registration secondRegistration;
125 Atomic<size_t> entered;
126 Atomic<size_t> attempts;
127 Atomic<size_t> rejections;
128 Atomic<size_t> resetReturns;
129 Atomic<size_t> failures;
130};
131
132uintptr_t ReciprocalUnregisterHandler::syscall(SyscallState&) {
133 m_Context.entered += 1;
134 const Time::Timestamp deadline = Time::getTicks() + (500 * Time::Multiplier::Millisecond);
135 while (m_Context.entered != static_cast<size_t>(2) && Time::getTicks() < deadline) {
137 }
138
139 if (m_Context.entered != static_cast<size_t>(2)) {
140 m_Context.failures += 1;
141 return 0;
142 }
143
144 m_Context.attempts += 1;
146 m_First ? m_Context.secondRegistration : m_Context.firstRegistration;
147 if (!peer.reset() && peer) {
148 m_Context.rejections += 1;
149 } else {
150 m_Context.failures += 1;
151 }
152 m_Context.resetReturns += 1;
153 const Time::Timestamp returnDeadline = Time::getTicks() + (500 * Time::Multiplier::Millisecond);
154 while (m_Context.resetReturns != static_cast<size_t>(2) && Time::getTicks() < returnDeadline) {
156 }
157 if (m_Context.resetReturns != static_cast<size_t>(2)) {
158 m_Context.failures += 1;
159 }
160 return m_First ? 0x53 : 0x54;
161}
162
163struct ReciprocalSyscallInvocation {
164 ReciprocalUnregisterContext* context;
165 Service_t service;
166 uintptr_t result;
167};
168
169int invokeReciprocalSyscall(void* parameter) {
170 ReciprocalSyscallInvocation* invocation =
171 reinterpret_cast<ReciprocalSyscallInvocation*>(parameter);
172 invocation->result = SyscallManager::instance().syscall(invocation->service, 0);
173 return 0;
174}
175
176bool reciprocalUnregisterRejected() {
178 ReciprocalUnregisterContext context;
179 const bool registered =
180 manager.registerSyscallHandler(TUI, &context.first, context.firstRegistration) &&
181 manager.registerSyscallHandler(native, &context.second, context.secondRegistration);
182 if (!registered) {
183 if (context.firstRegistration) {
184 context.firstRegistration.reset();
185 }
186 return check(false, "syscall-reciprocal-unregister",
187 "the reciprocal handlers could not register");
188 }
189
190 ReciprocalSyscallInvocation first = {&context, TUI, 0};
191 ReciprocalSyscallInvocation second = {&context, native, 0};
192 Thread* firstThread = new Thread(Scheduler::instance().getKernelProcess(),
193 invokeReciprocalSyscall, &first, nullptr, false, true);
194 Thread* secondThread = new Thread(Scheduler::instance().getKernelProcess(),
195 invokeReciprocalSyscall, &second, nullptr, false, true);
196 firstThread->setName("hosted syscall reciprocal first");
197 secondThread->setName("hosted syscall reciprocal second");
198
199 const bool firstJoined = firstThread->join();
200 const bool secondJoined = secondThread->join();
201 const bool registrationsPreserved = context.firstRegistration && context.secondRegistration;
202 const bool firstRetired = context.firstRegistration.reset();
203 const bool secondRetired = context.secondRegistration.reset();
204 const bool passed =
205 check(firstJoined && secondJoined && first.result == 0x53 && second.result == 0x54 &&
206 context.entered == 2 && context.attempts == 2 && context.rejections == 2 &&
207 context.resetReturns == 2 && context.failures == 0,
208 "syscall-reciprocal-unregister", "reciprocal callbacks did not finish cleanly") &&
209 check(registrationsPreserved && firstRetired && secondRetired,
210 "syscall-reciprocal-unregister",
211 "callback-context rejection lost external cleanup ownership");
212 if (passed) {
213 NOTICE("HOSTED-WAIT-TEST: PASS syscall-reciprocal-unregister");
214 }
215 return passed;
216}
217
218void handlerPinHook(Service_t service, SyscallHandler* handler) {
219 HandlerLifetimeContext* context = g_HandlerLifetimeContext;
220 if (!context || service != TUI || handler != &context->handler ||
221 !context->phase.compareAndSwap(0, 1)) {
222 return;
223 }
224
225 context->hookCalls += 1;
226 for (size_t attempt = 0; attempt < 10000; ++attempt) {
227 if (context->phase == static_cast<size_t>(2) && !context->unregisterReturned &&
228 SyscallManager::instance().syscall(TUI, 0) == 0) {
229 context->hookObservedDrain += 1;
230 context->phase = 3;
231 return;
232 }
234 }
235
236 context->failures += 1;
237 context->phase = 3;
238}
239
240int unregisterPinnedHandler(void* parameter) {
241 HandlerLifetimeContext* context = reinterpret_cast<HandlerLifetimeContext*>(parameter);
242 const Time::Timestamp deadline = Time::getTicks() + (500 * Time::Multiplier::Millisecond);
243 while (context->phase != static_cast<size_t>(1) && Time::getTicks() < deadline) {
245 }
246
247 if (context->phase != static_cast<size_t>(1)) {
248 context->failures += 1;
249 return 1;
250 }
251
252 if (!context->registration.closeAdmission()) {
253 context->failures += 1;
254 context->phase = 3;
255 return 1;
256 }
257 context->phase = 2;
258 if (context->registration.reset()) {
259 context->unregisterSucceeded += 1;
260 }
261 context->unregisterReturned += 1;
262 return 0;
263}
264
265bool handlerLifetimeBarrier() {
267 HandlerLifetimeContext context;
268 context.remover = new Thread(Scheduler::instance().getKernelProcess(), unregisterPinnedHandler,
269 &context, nullptr, false, true);
270 context.remover->setName("hosted syscall-handler remover");
271
272 g_HandlerLifetimeContext = &context;
273 manager.setHandlerPinHook(handlerPinHook);
274 const bool registered =
275 manager.registerSyscallHandler(TUI, &context.handler, context.registration);
277 const bool duplicateRejected =
278 !manager.registerSyscallHandler(TUI, &context.handler, duplicate) && !duplicate;
279 const uintptr_t result = manager.syscall(TUI, 0);
280 const bool joined = context.remover->join();
281 manager.setHandlerPinHook(nullptr);
282 g_HandlerLifetimeContext = nullptr;
283
284 const size_t callsAtUnregisterReturn = context.handlerCalls;
285 const uintptr_t lateResult = manager.syscall(TUI, 0);
286 const bool lateDispatchRejected = lateResult == 0 &&
287 context.handlerCalls == callsAtUnregisterReturn &&
288 context.callbacksAfterReturn == 0;
289
291 const bool reregistered = manager.registerSyscallHandler(TUI, &context.handler, reusable);
292 const uintptr_t redispatchResult = reregistered ? manager.syscall(TUI, 0) : 0;
293 SyscallManager::Registration moved(pedigree_std::move(reusable));
294 const bool movePreservedOwnership = !reusable && moved && moved.reset();
295
296 SyscallManager::Registration selfRegistration;
297 SelfUnregisteringHandler selfUnregistering(selfRegistration);
298 const bool selfRegistered =
299 manager.registerSyscallHandler(TUI, &selfUnregistering, selfRegistration);
300 const uintptr_t selfResult = selfRegistered ? manager.syscall(TUI, 0) : 0;
301 const bool selfCleanup = selfRegistered && selfRegistration.reset();
302
303 const bool passed =
304 check(registered && duplicateRejected && result == 0x51, "syscall-handler-lifetime",
305 "registration, token ownership, or dispatch failed") &&
306 check(joined && context.failures == 0, "syscall-handler-lifetime",
307 "the unregister worker did not finish cleanly") &&
308 check(context.hookCalls == 1 && context.hookObservedDrain == 1 &&
309 context.unregisterSucceeded == 1 && context.unregisterReturned == 1,
310 "syscall-handler-lifetime", "unregister returned before the admitted handler") &&
311 check(lateDispatchRejected, "syscall-handler-lifetime",
312 "a handler ran after token reset returned") &&
313 check(reregistered && redispatchResult == 0x51 && movePreservedOwnership,
314 "syscall-handler-lifetime", "generation-bearing token move or slot reuse failed") &&
315 check(selfRegistered && selfResult == 0x52 && selfUnregistering.calls == 1 &&
316 selfUnregistering.rejectionSeen == 1 && selfCleanup,
317 "syscall-handler-lifetime", "self-reset changed ownership or reported safe teardown");
318
319 if (passed) {
320 NOTICE("HOSTED-WAIT-TEST: PASS syscall-handler-lifetime");
321 }
322 return passed;
323}
324
325class PostActionHandler : public SyscallHandler {
326 public:
327 PostActionHandler() : requested(SyscallManager::NoPostSyscallAction), calls(0), failures(0) {}
328
329 uintptr_t syscall(SyscallState& syscallState) override {
330 calls += 1;
331 if (syscallState.getSyscallNumber() == 1) {
332 return 0x62;
333 }
334
335 Thread* thread = Processor::information().getCurrentThread();
336 void* dispatchContext = thread->getSyscallDispatchContext();
337 bool staged = false;
338 switch (requested) {
339 case SyscallManager::TerminateCurrentThread:
341 break;
342 case SyscallManager::ExitCurrentProcess:
343 staged = SyscallManager::instance().requestProcessExit(37);
344 break;
345 case SyscallManager::ReturnFromEvent:
346 staged = SyscallManager::instance().requestEventReturn();
347 break;
348 case SyscallManager::PopEventState:
349 staged = SyscallManager::instance().requestEventStatePop();
350 break;
351 case SyscallManager::RestoreProcessorState: {
352 ProcessorState state;
353 // Hosted IP/SP accessors are stubs; this is its actual copied payload.
354 state.state = 0x12345678;
355 staged = SyscallManager::instance().requestStateRestore(state);
356 volatile uint64_t* source = &state.state;
357 *source = 0x87654321;
358 break;
359 }
360 case SyscallManager::JumpToUserspace:
361 staged = SyscallManager::instance().requestUserJump(0x1234, 0x5678);
362 break;
363 case SyscallManager::RebootSystem:
364 staged = SyscallManager::instance().requestReboot();
365 break;
366 case SyscallManager::NoPostSyscallAction:
367 staged = true;
368 break;
369 }
370
371 if (!staged) {
372 failures += 1;
373 }
374 if (requested != SyscallManager::NoPostSyscallAction) {
375 ProcessorState rejectedState;
376 rejectedState.state = 0xabcdef;
377 if (SyscallManager::instance().requestUserJump(0xabcd, 0xef01) ||
378 SyscallManager::instance().requestStateRestore(rejectedState) ||
379 SyscallManager::instance().requestProcessExit(73)) {
380 failures += 1;
381 }
382 }
383 if (SyscallManager::instance().syscall(TUI, 1) != 0x62 ||
384 thread->getSyscallDispatchContext() != dispatchContext) {
385 failures += 1;
386 }
387 return 0x61;
388 }
389
390 SyscallManager::PostSyscallActionKind requested;
391 Atomic<size_t> calls;
392 Atomic<size_t> failures;
393};
394
395struct PostActionContext {
396 SyscallManager::PostSyscallActionKind expected = SyscallManager::NoPostSyscallAction;
397 intptr_t expectedValue = 0;
398 void* previousContext = nullptr;
399 SyscallManager::Registration* registration = nullptr;
400 Atomic<size_t> calls = 0;
401 Atomic<size_t> retired = 0;
402 Atomic<size_t> failures = 0;
403};
404
405PostActionContext* g_PostActionContext = nullptr;
406
407bool postActionHook(SyscallManager::PostSyscallActionKind kind, intptr_t value,
408 const ProcessorState* state) {
409 PostActionContext* context = g_PostActionContext;
410 if (!context) {
411 return false;
412 }
413
414 context->calls += 1;
415 Thread* thread = Processor::information().getCurrentThread();
416 if (kind != context->expected || value != context->expectedValue || !thread ||
417 thread->isTerminationDeferred() ||
418 thread->getSyscallDispatchContext() != context->previousContext) {
419 context->failures += 1;
420 }
421 const bool needsState =
422 kind == SyscallManager::RestoreProcessorState || kind == SyscallManager::JumpToUserspace;
423 if (needsState != (state != nullptr) ||
424 (state && state->state != (kind == SyscallManager::RestoreProcessorState ? 0x12345678 : 0))) {
425 context->failures += 1;
426 }
427 if (context->registration && context->registration->reset()) {
428 context->retired += 1;
429 } else {
430 context->failures += 1;
431 }
432 return true;
433}
434
435bool postSyscallActions() {
436 static const SyscallManager::PostSyscallActionKind actions[] = {
437 SyscallManager::TerminateCurrentThread, SyscallManager::ExitCurrentProcess,
438 SyscallManager::ReturnFromEvent, SyscallManager::PopEventState,
439 SyscallManager::RestoreProcessorState, SyscallManager::NoPostSyscallAction,
440 SyscallManager::JumpToUserspace, SyscallManager::RebootSystem};
441 constexpr size_t ActionCount = sizeof(actions) / sizeof(actions[0]);
442
444 PostActionHandler handler;
445 PostActionContext context;
446 Thread* thread = Processor::information().getCurrentThread();
447 context.previousContext = thread->getSyscallDispatchContext();
448 g_PostActionContext = &context;
449 manager.setPostSyscallHook(postActionHook);
450
451 bool loopPassed = true;
452 for (size_t i = 0; i < ActionCount; ++i) {
453 const bool needsEventState = actions[i] == SyscallManager::ReturnFromEvent ||
454 actions[i] == SyscallManager::PopEventState;
455 const bool stateReady = !needsEventState || (thread && thread->pushState() != nullptr);
456 SyscallManager::Registration registration;
457 context.expected = actions[i];
458 context.expectedValue = actions[i] == SyscallManager::ExitCurrentProcess ? 37 : 0;
459 context.registration = &registration;
460 handler.requested = actions[i];
461 const bool noAction = actions[i] == SyscallManager::NoPostSyscallAction;
462 const size_t hookCalls = context.calls;
463 const bool dispatched = stateReady &&
464 manager.registerSyscallHandler(TUI, &handler, registration) &&
465 manager.syscall(TUI, 0) == 0x61;
466 if (!dispatched || thread->getSyscallDispatchContext() != context.previousContext ||
467 (noAction ? !registration || context.calls != hookCalls || !registration.reset()
468 : static_cast<bool>(registration))) {
469 loopPassed = false;
470 if (registration) {
471 registration.reset();
472 }
473 }
474 if (needsEventState && stateReady) {
475 thread->popState();
476 }
477 }
478
479 manager.setPostSyscallHook(nullptr);
480 g_PostActionContext = nullptr;
481 const bool passed =
482 check(loopPassed && handler.calls == 2 * ActionCount && handler.failures == 0 &&
483 context.calls == ActionCount - 1 && context.retired == ActionCount - 1 &&
484 context.failures == 0,
485 "syscall-post-actions", "post-action state, nesting, rejection, or retirement failed");
486 if (passed) {
487 NOTICE("HOSTED-WAIT-TEST: PASS syscall-post-actions");
488 }
489 return passed;
490}
491
492class InvalidEventActionHandler : public SyscallHandler {
493 public:
494 InvalidEventActionHandler()
495 : requested(SyscallManager::NoPostSyscallAction), calls(0), rejections(0) {}
496
497 uintptr_t syscall(SyscallState&) override {
498 bool accepted = false;
499 if (requested == SyscallManager::ReturnFromEvent) {
500 accepted = SyscallManager::instance().requestEventReturn();
501 } else if (requested == SyscallManager::PopEventState) {
502 accepted = SyscallManager::instance().requestEventStatePop();
503 }
504
505 calls += 1;
506 if (!accepted) {
507 rejections += 1;
508 }
509 return 0x62;
510 }
511
512 SyscallManager::PostSyscallActionKind requested;
513 Atomic<size_t> calls;
514 Atomic<size_t> rejections;
515};
516
517bool baseStateEventActionsRejected() {
518 Thread* thread = Processor::information().getCurrentThread();
520 InvalidEventActionHandler handler;
521 SyscallManager::Registration registration;
522 const bool registered = thread && !thread->getStateLevel() &&
523 manager.registerSyscallHandler(TUI, &handler, registration);
524
525 handler.requested = SyscallManager::ReturnFromEvent;
526 const uintptr_t returnResult = registered ? manager.syscall(TUI, 0) : 0;
527 handler.requested = SyscallManager::PopEventState;
528 const uintptr_t popResult = registered ? manager.syscall(TUI, 0) : 0;
529 const bool retired = registered && registration.reset();
530
531 const bool passed =
532 check(registered && returnResult == 0x62 && popResult == 0x62 && handler.calls == 2 &&
533 handler.rejections == 2 && retired && !thread->getStateLevel(),
534 "syscall-event-action-boundary", "a base-state event return or pop was accepted");
535 if (passed) {
536 NOTICE(
537 "HOSTED-WAIT-TEST: PASS "
538 "syscall-event-action-boundary");
539 }
540 return passed;
541}
542
543struct AbandonedStackContext;
544
545class AbandoningHandler : public SyscallHandler {
546 public:
547 explicit AbandoningHandler(AbandonedStackContext& context) : m_Context(context) {}
548
549 uintptr_t syscall(SyscallState&) override;
550
551 private:
552 AbandonedStackContext& m_Context;
553};
554
555struct AbandonedStackContext {
556 AbandonedStackContext() : handler(*this), entered(0), returned(0), destructed(0) {}
557
558 AbandoningHandler handler;
559 Atomic<size_t> entered;
560 Atomic<size_t> returned;
561 Atomic<size_t> destructed;
562};
563
564class AbandonedStackCanary {
565 public:
566 explicit AbandonedStackCanary(Atomic<size_t>* destructed) : m_Destructed(destructed) {}
567
568 ~AbandonedStackCanary() {
569 *m_Destructed += 1;
570 }
571
572 private:
573 Atomic<size_t>* m_Destructed;
574};
575
576uintptr_t AbandoningHandler::syscall(SyscallState&) {
577 Thread* thread = Processor::information().getCurrentThread();
578 if (!thread->pushState()) {
579 return 0;
580 }
581
582 Uninterruptible eventAndTerminationDeferral;
583 TerminationDeferral nestedTerminationDeferral;
584 AbandonedStackCanary stackCanary(&m_Context.destructed);
585 m_Context.entered += 1;
587 PerProcessorScheduler::StackDiscardReason::HostedRegression);
588}
589
590int invokeAbandoningSyscall(void* parameter) {
591 AbandonedStackContext* context = reinterpret_cast<AbandonedStackContext*>(parameter);
593 context->returned += 1;
594 return 1;
595}
596
597bool abandonedSyscallStack() {
599 AbandonedStackContext context;
600 SyscallManager::Registration registration;
601 if (!manager.registerSyscallHandler(TUI, &context.handler, registration)) {
602 return check(false, "syscall-abandoned-stack", "the abandoning handler could not register");
603 }
604
605 const size_t discardsBefore = PerProcessorScheduler::stackDiscardCount(
606 PerProcessorScheduler::StackDiscardReason::HostedRegression);
607 Thread* thread = new Thread(Scheduler::instance().getKernelProcess(), invokeAbandoningSyscall,
608 &context, nullptr, false, true);
609 thread->setName("hosted abandoning syscall");
610 const bool joined = thread->join();
611 const bool retired = registration.reset();
612
613 const bool passed = check(
614 joined && retired && context.entered == 1 && context.returned == 0 &&
615 context.destructed == 0 &&
617 PerProcessorScheduler::StackDiscardReason::HostedRegression) == discardsBefore + 1,
618 "syscall-abandoned-stack",
619 "forced teardown did not count exactly one intentionally leaked stack");
620 if (passed) {
621 NOTICE("HOSTED-WAIT-TEST: PASS syscall-abandoned-stack");
622 }
623 return passed;
624}
625} // namespace
626
627bool runHostedPostSyscallRegressions() {
628 return postSyscallActions() && baseStateEventActionsRejected();
629}
630
631bool runHostedSyscallRegressions() {
632 return handlerLifetimeBarrier() && reciprocalUnregisterRejected() && postSyscallActions() &&
633 baseStateEventActionsRejected() && abandonedSyscallStack();
634}
void abandonCurrentThreadStack(StackDiscardReason reason, Spinlock *pLock=0) NORETURN
static ProcessorInformation & information()
static Scheduler & instance()
Definition Scheduler.h:96
void yield()
Definition Scheduler.cc:236
virtual uintptr_t syscall(SyscallState &State)=0
virtual uintptr_t syscall(Service_t service, uintptr_t function, uintptr_t p1=0, uintptr_t p2=0, uintptr_t p3=0, uintptr_t p4=0, uintptr_t p5=0)=0
virtual bool registerSyscallHandler(Service_t Service, SyscallHandler *pHandler, Registration &registration, FastEntry entry=nullptr)=0
static EXPORTED_PUBLIC SyscallManager & instance()
EXPORTED_PUBLIC bool requestThreadExit()
bool join()
Definition Thread.cc:2746
void popState(bool clean=true)
Definition Thread.cc:913
class PerProcessorScheduler * getScheduler() const
Definition Thread.h:929
bool isTerminationDeferred() const
Definition Thread.h:569
SchedulerState * pushState()
Definition Thread.cc:841
size_t getStateLevel() const
Definition Thread.h:316