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_LegacyUserCallbackPins ||
52 m_SignalFramesRequired)
53 return false;
54 __atomic_store_n(&m_SignalFramesRequired, true, __ATOMIC_RELEASE);
55 markUserReturnWorkFlag(UserReturnSignalFrames);
56 return true;
57}
58
59void Thread::clearSignalFrameRequirement() {
61 __atomic_store_n(&m_SignalFramesRequired, false, __ATOMIC_RELEASE);
62 clearUserReturnWorkFlag(UserReturnSignalFrames);
63}
64
66 return event->requiresExactUserReturnState() ||
67 (m_SignalFramesRequired && event->isSignalEvent() && event->getNumber() != 9);
68}
69
70void Thread::setUserReturnSignalParked(bool parked) {
72 if (Processor::information().getCurrentThread() != this)
73 FATAL("User-return signal park has a foreign owner");
74 m_UserReturnSignalParked = parked;
75 if (parked)
76 markUserReturnWorkPending();
77}
78
79bool Thread::canSkipUserReturnWork() {
80 Process* process = m_pParent;
81 const bool workPending = userReturnWorkPending();
82 return process && process->getState() == Process::Active && getUnwindState() == Continue &&
83 !workPending && m_OriginalSyscallState == nullptr;
84}
85
86bool Thread::clearUserReturnWorkIfIdle() {
88 const StateLevel& state = m_StateLevels[m_nStateLevel];
89 if (!m_pParent || m_pParent->getState() != Process::Active || m_EventQueue.count() ||
91 state.m_DeferredSignalMaskRestore || m_UserReturnSignalParked || m_SignalFramesRequired ||
92 __atomic_load_n(&m_DeferredSubsystemExceptionState, __ATOMIC_ACQUIRE) ||
93 m_OriginalSyscallState) {
94 return false;
95 }
96 __atomic_store_n(&m_UserReturnWorkPending, static_cast<size_t>(0), __ATOMIC_RELEASE);
97 return true;
98}
Definition Event.h:49
static ProcessorInformation & information()
size_t m_DeferredSubsystemExceptionState
Definition Thread.h:1323
@ Continue
No unwind necessary, carry on as normal.
Definition Thread.h:513
SchedulerState & state()
Definition Thread.cc:875
bool m_bShutdown
Definition Thread.h:1332
size_t m_EventDeferralDepth
Definition Thread.h:1372
Process * m_pParent
Definition Thread.h:1176
UnwindType getUnwindState()
Definition Thread.h:531
Spinlock m_Lock
Definition Thread.h:1257
bool eventNeedsUserReturnFrameUnlocked(Event *event) const
size_t m_nStateLevel
Definition Thread.h:1173
size_t m_TerminationDeferralDepth
Definition Thread.h:1375
List< Event * > m_EventQueue
Definition Thread.h:1289
size_t count() const
Definition List.h:212