The Pedigree Project 0.1
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 Thread::WaitDebugInfo info = {};
228 uintptr_t debugAddress = 0;
229 if (context->phase == static_cast<size_t>(2) && context->remover->getWaitDebugInfo(info) &&
230 info.queue && info.channelOwner && info.queued &&
231 context->remover->getDebugState(debugAddress) == Thread::CallbackDrain &&
232 debugAddress == reinterpret_cast<uintptr_t>(&context->handler)) {
233 context->hookObservedDrain += 1;
234 context->phase = 3;
235 return;
236 }
238 }
239
240 context->failures += 1;
241 context->phase = 3;
242}
243
244int unregisterPinnedHandler(void* parameter) {
245 HandlerLifetimeContext* context = reinterpret_cast<HandlerLifetimeContext*>(parameter);
246 const Time::Timestamp deadline = Time::getTicks() + (500 * Time::Multiplier::Millisecond);
247 while (context->phase != static_cast<size_t>(1) && Time::getTicks() < deadline) {
249 }
250
251 if (context->phase != static_cast<size_t>(1)) {
252 context->failures += 1;
253 return 1;
254 }
255
256 context->phase = 2;
257 if (context->registration.reset()) {
258 context->unregisterSucceeded += 1;
259 }
260 context->unregisterReturned += 1;
261 return 0;
262}
263
264bool handlerLifetimeBarrier() {
266 HandlerLifetimeContext context;
267 context.remover = new Thread(Scheduler::instance().getKernelProcess(), unregisterPinnedHandler,
268 &context, nullptr, false, true);
269 context.remover->setName("hosted syscall-handler remover");
270
271 g_HandlerLifetimeContext = &context;
272 manager.setHandlerPinHook(handlerPinHook);
273 const bool registered =
274 manager.registerSyscallHandler(TUI, &context.handler, context.registration);
276 const bool duplicateRejected =
277 !manager.registerSyscallHandler(TUI, &context.handler, duplicate) && !duplicate;
278 const uintptr_t result = manager.syscall(TUI, 0);
279 const bool joined = context.remover->join();
280 manager.setHandlerPinHook(nullptr);
281 g_HandlerLifetimeContext = nullptr;
282
283 const size_t callsAtUnregisterReturn = context.handlerCalls;
284 const uintptr_t lateResult = manager.syscall(TUI, 0);
285 const bool lateDispatchRejected = lateResult == 0 &&
286 context.handlerCalls == callsAtUnregisterReturn &&
287 context.callbacksAfterReturn == 0;
288
290 const bool reregistered = manager.registerSyscallHandler(TUI, &context.handler, reusable);
291 const uintptr_t redispatchResult = reregistered ? manager.syscall(TUI, 0) : 0;
292 SyscallManager::Registration moved(pedigree_std::move(reusable));
293 const bool movePreservedOwnership = !reusable && moved && moved.reset();
294
295 SyscallManager::Registration selfRegistration;
296 SelfUnregisteringHandler selfUnregistering(selfRegistration);
297 const bool selfRegistered =
298 manager.registerSyscallHandler(TUI, &selfUnregistering, selfRegistration);
299 const uintptr_t selfResult = selfRegistered ? manager.syscall(TUI, 0) : 0;
300 const bool selfCleanup = selfRegistered && selfRegistration.reset();
301
302 const bool passed =
303 check(registered && duplicateRejected && result == 0x51, "syscall-handler-lifetime",
304 "registration, token ownership, or dispatch failed") &&
305 check(joined && context.failures == 0, "syscall-handler-lifetime",
306 "the unregister worker did not finish cleanly") &&
307 check(context.hookCalls == 1 && context.hookObservedDrain == 1 &&
308 context.unregisterSucceeded == 1 && context.unregisterReturned == 1,
309 "syscall-handler-lifetime", "unregister returned before the admitted handler") &&
310 check(lateDispatchRejected, "syscall-handler-lifetime",
311 "a handler ran after token reset returned") &&
312 check(reregistered && redispatchResult == 0x51 && movePreservedOwnership,
313 "syscall-handler-lifetime", "generation-bearing token move or slot reuse failed") &&
314 check(selfRegistered && selfResult == 0x52 && selfUnregistering.calls == 1 &&
315 selfUnregistering.rejectionSeen == 1 && selfCleanup,
316 "syscall-handler-lifetime", "self-reset changed ownership or reported safe teardown");
317
318 if (passed) {
319 NOTICE("HOSTED-WAIT-TEST: PASS syscall-handler-lifetime");
320 }
321 return passed;
322}
323
324class PostActionHandler : public SyscallHandler {
325 public:
326 PostActionHandler() : requested(SyscallManager::NoPostSyscallAction), calls(0), failures(0) {}
327
328 uintptr_t syscall(SyscallState& syscallState) override {
329 calls += 1;
330 if (syscallState.getSyscallNumber() == 1) {
331 return 0x62;
332 }
333
334 Thread* thread = Processor::information().getCurrentThread();
335 void* dispatchContext = thread->getSyscallDispatchContext();
336 bool staged = false;
337 switch (requested) {
338 case SyscallManager::TerminateCurrentThread:
340 break;
341 case SyscallManager::ExitCurrentProcess:
342 staged = SyscallManager::instance().requestProcessExit(37);
343 break;
344 case SyscallManager::ReturnFromEvent:
345 staged = SyscallManager::instance().requestEventReturn();
346 break;
347 case SyscallManager::PopEventState:
348 staged = SyscallManager::instance().requestEventStatePop();
349 break;
350 case SyscallManager::RestoreProcessorState: {
351 ProcessorState state;
352 // Hosted IP/SP accessors are stubs; this is its actual copied payload.
353 state.state = 0x12345678;
354 staged = SyscallManager::instance().requestStateRestore(state);
355 volatile uint64_t* source = &state.state;
356 *source = 0x87654321;
357 break;
358 }
359 case SyscallManager::JumpToUserspace:
360 staged = SyscallManager::instance().requestUserJump(0x1234, 0x5678);
361 break;
362 case SyscallManager::RebootSystem:
363 staged = SyscallManager::instance().requestReboot();
364 break;
365 case SyscallManager::NoPostSyscallAction:
366 staged = true;
367 break;
368 }
369
370 if (!staged) {
371 failures += 1;
372 }
373 if (requested != SyscallManager::NoPostSyscallAction) {
374 ProcessorState rejectedState;
375 rejectedState.state = 0xabcdef;
376 if (SyscallManager::instance().requestUserJump(0xabcd, 0xef01) ||
377 SyscallManager::instance().requestStateRestore(rejectedState) ||
378 SyscallManager::instance().requestProcessExit(73)) {
379 failures += 1;
380 }
381 }
382 if (SyscallManager::instance().syscall(TUI, 1) != 0x62 ||
383 thread->getSyscallDispatchContext() != dispatchContext) {
384 failures += 1;
385 }
386 return 0x61;
387 }
388
389 SyscallManager::PostSyscallActionKind requested;
390 Atomic<size_t> calls;
391 Atomic<size_t> failures;
392};
393
394struct PostActionContext {
395 SyscallManager::PostSyscallActionKind expected = SyscallManager::NoPostSyscallAction;
396 intptr_t expectedValue = 0;
397 void* previousContext = nullptr;
398 SyscallManager::Registration* registration = nullptr;
399 Atomic<size_t> calls = 0;
400 Atomic<size_t> retired = 0;
401 Atomic<size_t> failures = 0;
402};
403
404PostActionContext* g_PostActionContext = nullptr;
405
406bool postActionHook(SyscallManager::PostSyscallActionKind kind, intptr_t value,
407 const ProcessorState* state) {
408 PostActionContext* context = g_PostActionContext;
409 if (!context) {
410 return false;
411 }
412
413 context->calls += 1;
414 Thread* thread = Processor::information().getCurrentThread();
415 if (kind != context->expected || value != context->expectedValue || !thread ||
416 thread->isTerminationDeferred() ||
417 thread->getSyscallDispatchContext() != context->previousContext) {
418 context->failures += 1;
419 }
420 const bool needsState =
421 kind == SyscallManager::RestoreProcessorState || kind == SyscallManager::JumpToUserspace;
422 if (needsState != (state != nullptr) ||
423 (state && state->state != (kind == SyscallManager::RestoreProcessorState ? 0x12345678 : 0))) {
424 context->failures += 1;
425 }
426 if (context->registration && context->registration->reset()) {
427 context->retired += 1;
428 } else {
429 context->failures += 1;
430 }
431 return true;
432}
433
434bool postSyscallActions() {
435 static const SyscallManager::PostSyscallActionKind actions[] = {
436 SyscallManager::TerminateCurrentThread, SyscallManager::ExitCurrentProcess,
437 SyscallManager::ReturnFromEvent, SyscallManager::PopEventState,
438 SyscallManager::RestoreProcessorState, SyscallManager::NoPostSyscallAction,
439 SyscallManager::JumpToUserspace, SyscallManager::RebootSystem};
440 constexpr size_t ActionCount = sizeof(actions) / sizeof(actions[0]);
441
443 PostActionHandler handler;
444 PostActionContext context;
445 Thread* thread = Processor::information().getCurrentThread();
446 context.previousContext = thread->getSyscallDispatchContext();
447 g_PostActionContext = &context;
448 manager.setPostSyscallHook(postActionHook);
449
450 bool loopPassed = true;
451 for (size_t i = 0; i < ActionCount; ++i) {
452 const bool needsEventState = actions[i] == SyscallManager::ReturnFromEvent ||
453 actions[i] == SyscallManager::PopEventState;
454 const bool stateReady = !needsEventState || (thread && thread->pushState() != nullptr);
455 SyscallManager::Registration registration;
456 context.expected = actions[i];
457 context.expectedValue = actions[i] == SyscallManager::ExitCurrentProcess ? 37 : 0;
458 context.registration = &registration;
459 handler.requested = actions[i];
460 const bool noAction = actions[i] == SyscallManager::NoPostSyscallAction;
461 const size_t hookCalls = context.calls;
462 const bool dispatched = stateReady &&
463 manager.registerSyscallHandler(TUI, &handler, registration) &&
464 manager.syscall(TUI, 0) == 0x61;
465 if (!dispatched || thread->getSyscallDispatchContext() != context.previousContext ||
466 (noAction ? !registration || context.calls != hookCalls || !registration.reset()
467 : static_cast<bool>(registration))) {
468 loopPassed = false;
469 if (registration) {
470 registration.reset();
471 }
472 }
473 if (needsEventState && stateReady) {
474 thread->popState();
475 }
476 }
477
478 manager.setPostSyscallHook(nullptr);
479 g_PostActionContext = nullptr;
480 const bool passed =
481 check(loopPassed && handler.calls == 2 * ActionCount && handler.failures == 0 &&
482 context.calls == ActionCount - 1 && context.retired == ActionCount - 1 &&
483 context.failures == 0,
484 "syscall-post-actions", "post-action state, nesting, rejection, or retirement failed");
485 if (passed) {
486 NOTICE("HOSTED-WAIT-TEST: PASS syscall-post-actions");
487 }
488 return passed;
489}
490
491class InvalidEventActionHandler : public SyscallHandler {
492 public:
493 InvalidEventActionHandler()
494 : requested(SyscallManager::NoPostSyscallAction), calls(0), rejections(0) {}
495
496 uintptr_t syscall(SyscallState&) override {
497 bool accepted = false;
498 if (requested == SyscallManager::ReturnFromEvent) {
499 accepted = SyscallManager::instance().requestEventReturn();
500 } else if (requested == SyscallManager::PopEventState) {
501 accepted = SyscallManager::instance().requestEventStatePop();
502 }
503
504 calls += 1;
505 if (!accepted) {
506 rejections += 1;
507 }
508 return 0x62;
509 }
510
511 SyscallManager::PostSyscallActionKind requested;
512 Atomic<size_t> calls;
513 Atomic<size_t> rejections;
514};
515
516bool baseStateEventActionsRejected() {
517 Thread* thread = Processor::information().getCurrentThread();
519 InvalidEventActionHandler handler;
520 SyscallManager::Registration registration;
521 const bool registered = thread && !thread->getStateLevel() &&
522 manager.registerSyscallHandler(TUI, &handler, registration);
523
524 handler.requested = SyscallManager::ReturnFromEvent;
525 const uintptr_t returnResult = registered ? manager.syscall(TUI, 0) : 0;
526 handler.requested = SyscallManager::PopEventState;
527 const uintptr_t popResult = registered ? manager.syscall(TUI, 0) : 0;
528 const bool retired = registered && registration.reset();
529
530 const bool passed =
531 check(registered && returnResult == 0x62 && popResult == 0x62 && handler.calls == 2 &&
532 handler.rejections == 2 && retired && !thread->getStateLevel(),
533 "syscall-event-action-boundary", "a base-state event return or pop was accepted");
534 if (passed) {
535 NOTICE(
536 "HOSTED-WAIT-TEST: PASS "
537 "syscall-event-action-boundary");
538 }
539 return passed;
540}
541
542struct AbandonedStackContext;
543
544class AbandoningHandler : public SyscallHandler {
545 public:
546 explicit AbandoningHandler(AbandonedStackContext& context) : m_Context(context) {}
547
548 uintptr_t syscall(SyscallState&) override;
549
550 private:
551 AbandonedStackContext& m_Context;
552};
553
554struct AbandonedStackContext {
555 AbandonedStackContext() : handler(*this), entered(0), returned(0), destructed(0) {}
556
557 AbandoningHandler handler;
558 Atomic<size_t> entered;
559 Atomic<size_t> returned;
560 Atomic<size_t> destructed;
561};
562
563class AbandonedStackCanary {
564 public:
565 explicit AbandonedStackCanary(Atomic<size_t>* destructed) : m_Destructed(destructed) {}
566
567 ~AbandonedStackCanary() {
568 *m_Destructed += 1;
569 }
570
571 private:
572 Atomic<size_t>* m_Destructed;
573};
574
575uintptr_t AbandoningHandler::syscall(SyscallState&) {
576 Thread* thread = Processor::information().getCurrentThread();
577 if (!thread->pushState()) {
578 return 0;
579 }
580
581 Uninterruptible eventAndTerminationDeferral;
582 TerminationDeferral nestedTerminationDeferral;
583 AbandonedStackCanary stackCanary(&m_Context.destructed);
584 m_Context.entered += 1;
586 PerProcessorScheduler::StackDiscardReason::HostedRegression);
587}
588
589int invokeAbandoningSyscall(void* parameter) {
590 AbandonedStackContext* context = reinterpret_cast<AbandonedStackContext*>(parameter);
592 context->returned += 1;
593 return 1;
594}
595
596bool abandonedSyscallStack() {
598 AbandonedStackContext context;
599 SyscallManager::Registration registration;
600 if (!manager.registerSyscallHandler(TUI, &context.handler, registration)) {
601 return check(false, "syscall-abandoned-stack", "the abandoning handler could not register");
602 }
603
604 const size_t discardsBefore = PerProcessorScheduler::stackDiscardCount(
605 PerProcessorScheduler::StackDiscardReason::HostedRegression);
606 Thread* thread = new Thread(Scheduler::instance().getKernelProcess(), invokeAbandoningSyscall,
607 &context, nullptr, false, true);
608 thread->setName("hosted abandoning syscall");
609 const bool joined = thread->join();
610 const bool retired = registration.reset();
611
612 const bool passed = check(
613 joined && retired && context.entered == 1 && context.returned == 0 &&
614 context.destructed == 0 &&
616 PerProcessorScheduler::StackDiscardReason::HostedRegression) == discardsBefore + 1,
617 "syscall-abandoned-stack",
618 "forced teardown did not count exactly one intentionally leaked stack");
619 if (passed) {
620 NOTICE("HOSTED-WAIT-TEST: PASS syscall-abandoned-stack");
621 }
622 return passed;
623}
624} // namespace
625
626bool runHostedPostSyscallRegressions() {
627 return postSyscallActions() && baseStateEventActionsRejected();
628}
629
630bool runHostedSyscallRegressions() {
631 return handlerLifetimeBarrier() && reciprocalUnregisterRejected() && postSyscallActions() &&
632 baseStateEventActionsRejected() && abandonedSyscallStack();
633}
void abandonCurrentThreadStack(StackDiscardReason reason, Spinlock *pLock=0) NORETURN
static ProcessorInformation & information()
static Scheduler & instance()
Definition Scheduler.h:96
void yield()
Definition Scheduler.cc:226
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:2767
void popState(bool clean=true)
Definition Thread.cc:956
class PerProcessorScheduler * getScheduler() const
Definition Thread.h:925
bool isTerminationDeferred() const
Definition Thread.h:565
SchedulerState * pushState()
Definition Thread.cc:884
size_t getStateLevel() const
Definition Thread.h:314