The Pedigree Project 0.1
Thread-user-return.cc
1/* Copyright (c) 2026, Pedigree Developers. */
2#include "pedigree/kernel/LockGuard.h"
3#include "pedigree/kernel/Log.h"
4#include "pedigree/kernel/process/Process.h"
5#include "pedigree/kernel/process/Thread.h"
6#include "pedigree/kernel/processor/Processor.h"
7#include "pedigree/kernel/processor/UserReturnFrame.h"
8
9Thread::UserReturnFrameScope::UserReturnFrameScope(Thread& owner, UserReturnFrame& frame)
10 : m_Owner(&owner), m_StateLevel(0), m_Frame(&frame), m_Previous(nullptr), m_Record() {
11 EnsureInterrupts interrupts(false);
12 if (Processor::information().getCurrentThread() != &owner || frame.m_Owner != &owner)
13 FATAL("User-return frame scope has a foreign owner");
14 m_StateLevel = owner.m_nStateLevel;
15 m_Previous = owner.m_StateLevels[m_StateLevel].m_UserReturnFrame;
16 owner.armStateCleanup(m_Record, &UserReturnFrameScope::restore, this);
17 owner.m_StateLevels[m_StateLevel].m_UserReturnFrame = &frame;
18}
19
20Thread::UserReturnFrameScope::~UserReturnFrameScope() {
21 EnsureInterrupts interrupts(false);
22 if (m_Owner) {
23 m_Owner->disarmStateCleanup(m_Record);
24 restore(this);
25 }
26}
27
28void Thread::UserReturnFrameScope::restore(void* context) {
29 auto& scope = *static_cast<UserReturnFrameScope*>(context);
30 EnsureInterrupts interrupts(false);
31 if (!scope.m_Owner)
32 return;
33 if (Processor::information().getCurrentThread() != scope.m_Owner)
34 FATAL("User-return frame scope retired on a foreign Thread");
35 auto& slot = scope.m_Owner->m_StateLevels[scope.m_StateLevel].m_UserReturnFrame;
36 if (slot != scope.m_Frame)
37 FATAL("User-return frame scopes retired out of order");
38 slot = scope.m_Previous;
39 scope.m_Owner = nullptr;
40}
41
42UserReturnFrame* Thread::currentUserReturnFrame() const {
43 EnsureInterrupts interrupts(false);
44 if (Processor::information().getCurrentThread() != this)
45 return nullptr;
46 return m_StateLevels[m_nStateLevel].m_UserReturnFrame;
47}
48
49bool Thread::tryRequireSignalFrames() {
51 if (m_bShutdown || getUnwindState() != Continue || m_SignalFramesRequired)
52 return false;
53 __atomic_store_n(&m_SignalFramesRequired, true, __ATOMIC_RELEASE);
54 markUserReturnWorkFlag(UserReturnSignalFrames);
55 return true;
56}
57
58void Thread::clearSignalFrameRequirement() {
60 __atomic_store_n(&m_SignalFramesRequired, false, __ATOMIC_RELEASE);
61 clearUserReturnWorkFlag(UserReturnSignalFrames);
62}
63
65 return event->requiresExactUserReturnState() ||
66 (m_SignalFramesRequired && event->isSignalEvent() && event->getNumber() != 9);
67}
68
69void Thread::setUserReturnSignalParked(bool parked) {
71 if (Processor::information().getCurrentThread() != this)
72 FATAL("User-return signal park has a foreign owner");
73 m_UserReturnSignalParked = parked;
74 if (parked)
75 markUserReturnWorkPending();
76}
77
78bool Thread::canSkipUserReturnWork() {
79 Process* process = m_pParent;
80 const bool workPending = userReturnWorkPending();
81 return process && process->getState() == Process::Active && getUnwindState() == Continue &&
82 !workPending && m_OriginalSyscallState == nullptr;
83}
84
85bool Thread::clearUserReturnWorkIfIdle() {
87 const StateLevel& state = m_StateLevels[m_nStateLevel];
88 if (!m_pParent || m_pParent->getState() != Process::Active || m_EventQueue.count() ||
90 state.m_DeferredSignalMaskRestore || m_UserReturnSignalParked || m_SignalFramesRequired ||
91 __atomic_load_n(&m_DeferredSubsystemExceptionState, __ATOMIC_ACQUIRE) ||
92 m_OriginalSyscallState) {
93 return false;
94 }
95 __atomic_store_n(&m_UserReturnWorkPending, static_cast<size_t>(0), __ATOMIC_RELEASE);
96 return true;
97}
Definition Event.h:49
static ProcessorInformation & information()
size_t m_DeferredSubsystemExceptionState
Definition Thread.h:1330
@ Continue
No unwind necessary, carry on as normal.
Definition Thread.h:517
SchedulerState & state()
Definition Thread.cc:832
bool m_bShutdown
Definition Thread.h:1339
size_t m_EventDeferralDepth
Definition Thread.h:1379
Process * m_pParent
Definition Thread.h:1180
UnwindType getUnwindState()
Definition Thread.h:535
Spinlock m_Lock
Definition Thread.h:1262
bool eventNeedsUserReturnFrameUnlocked(Event *event) const
size_t m_nStateLevel
Definition Thread.h:1177
size_t m_TerminationDeferralDepth
Definition Thread.h:1387
List< Event * > m_EventQueue
Definition Thread.h:1294
size_t count() const
Definition List.h:212