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/Semaphore.h"
13#include "pedigree/kernel/process/Thread.h"
14#include "pedigree/kernel/processor/Processor.h"
15#include "pedigree/kernel/processor/ProcessorInformation.h"
16#include "pedigree/kernel/processor/SyscallManager.h"
21 LifetimeHandler() : entered(0), release(0), own(nullptr), peer(nullptr), abandon(false) {}
23 uintptr_t
syscall(SyscallState&)
override {
24 if (own && (own->reset() || !*own)) {
25 FATAL(
"QEMU syscall self-removal lost ownership");
27 if (peer && (!peer->reset() || *peer)) {
28 FATAL(
"QEMU syscall idle peer could not retire");
33 PerProcessorScheduler::StackDiscardReason::HostedRegression);
37 if (!release.acquireForCompletion()) {
38 FATAL(
"QEMU syscall lifetime wait interrupted");
52 return handler->
syscall(state) + 0x100;
57 explicit NestedRetirementHandler(
bool inner) : m_Inner(inner) {}
59 uintptr_t
syscall(SyscallState&)
override {
66 if (!manager.requestUserJump(0x1000, 0x2000)) {
67 FATAL(
"QEMU ancestor retirement lost the nested syscall action");
72 FATAL(
"QEMU syscall nested state could not be created");
75 if (manager.dispatchHandlerForTest(native, result) || result != 0x62) {
76 FATAL(
"QEMU nested syscall action was not retained");
80 FATAL(
"QEMU ancestor retirement left a stale syscall context");
91 bool returned =
false;
94int invoke(
void* parameter) {
95 Invocation* invocation =
static_cast<Invocation*
>(parameter);
102 : registration(token), closed(0), retired(0) {}
108int remove(
void* parameter) {
109 Removal* removal =
static_cast<Removal*
>(parameter);
110 if (!removal->registration.closeAdmission()) {
111 FATAL(
"QEMU syscall admission could not close");
113 removal->closed.release();
114 if (!removal->registration.reset()) {
115 FATAL(
"QEMU syscall admitted callback could not drain");
117 removal->retired = 1;
122bool runSyscallLifetimeRegression() {
123 NOTICE(
"QEMU-CONCURRENCY-TEST: BEGIN syscall-handler-lifetime");
126 LifetimeHandler handler, peer;
132 handler.own = ®istration;
133 handler.peer = &peerRegistration;
134 Invocation invocation;
135 Thread* callback =
new Thread(process, invoke, &invocation);
136 if (!handler.entered.acquireForCompletion()) {
139 Removal removal(registration);
140 Thread* remover =
new Thread(process, remove, &removal);
141 if (!removal.closed.acquireForCompletion()) {
145 void* dispatchContext = thread->getSyscallDispatchContext();
147 uintptr_t result = 0;
148 if (manager.dispatchHandlerForTest(TUI, result) ||
149 thread->getSyscallDispatchContext() != dispatchContext ||
153 for (
size_t i = 0; i < 32; ++i) {
155 if (removal.retired) {
159 handler.release.release();
161 invocation.result != 0x151 || !removal.retired || registration || peerRegistration) {
168 !manager.dispatchHandlerForTest(TUI, result) || result != 0x51 || !registration.reset()) {
176 Invocation abandoned;
177 Thread* discarded =
new Thread(process, invoke, &abandoned);
178 if (!discarded->
joinForCompletion() || abandoned.returned || !registration.reset()) {
182 NestedRetirementHandler outer(
false), inner(
true);
189 if (!nesting->
joinForCompletion() || !nested.returned || nested.result != 0x63 ||
190 !registration.reset() || !peerRegistration.reset()) {
193 NOTICE(
"QEMU-CONCURRENCY-TEST: PASS syscall-handler-lifetime");
void abandonCurrentThreadStack(StackDiscardReason reason, Spinlock *pLock=0) NORETURN
static ProcessorInformation & information()
static Scheduler & instance()
virtual uintptr_t syscall(SyscallState &State)=0
virtual bool registerSyscallHandler(Service_t Service, SyscallHandler *pHandler, Registration ®istration, FastEntry entry=nullptr)=0
static EXPORTED_PUBLIC SyscallManager & instance()
EXPORTED_PUBLIC bool requestThreadExit()
void popState(bool clean=true)
void prepareSignalStateForExec()
class PerProcessorScheduler * getScheduler() const
bool isTerminationDeferred() const
SchedulerState * pushState()