The Pedigree Project 0.1
ExecutionContext.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/Log.h"
9#include "pedigree/kernel/process/ExecutionContext.h"
10#include "pedigree/kernel/process/Thread.h"
11#include "pedigree/kernel/processor/Processor.h"
12#include "pedigree/kernel/processor/ProcessorInformation.h"
13
14ExecutionContextGuard::ExecutionContextGuard(ExecutionContext context)
15 : m_Thread(nullptr), m_StateLevel(0), m_Previous(ExecutionContext::AtomicThread), m_Cleanup() {
16 Thread* thread = Processor::information().getCurrentThread();
17 if (!thread) {
18 return;
19 }
20
21 const bool interruptsWereEnabled = Processor::getInterrupts();
23
24 m_StateLevel = __atomic_load_n(&thread->m_nStateLevel, __ATOMIC_ACQUIRE);
25 m_Previous = thread->m_StateLevels[m_StateLevel].m_ExecutionContext.current();
26
27 // Publish abandonment cleanup before changing the classification. A
28 // nested fault can therefore never leave a reused Thread state labelled
29 // as an IRQ context.
30 thread->armAtomicStateCleanup(m_Cleanup, abandon, this);
31 m_Thread = thread;
32 thread->m_StateLevels[m_StateLevel].m_ExecutionContext.enter(context);
33
34 Processor::setInterrupts(interruptsWereEnabled);
35}
36
37ExecutionContextGuard::~ExecutionContextGuard() {
38 Thread* thread = m_Thread;
39 if (!thread) {
40 return;
41 }
42
43 const bool interruptsWereEnabled = Processor::getInterrupts();
45 restore();
46 thread->disarmAtomicStateCleanup(m_Cleanup);
47 Processor::setInterrupts(interruptsWereEnabled);
48}
49
50void ExecutionContextGuard::abandon(void* context) {
51 ExecutionContextGuard* guard = reinterpret_cast<ExecutionContextGuard*>(context);
52 if (guard) {
53 guard->restore();
54 }
55}
56
57void ExecutionContextGuard::restore() {
58 if (!m_Thread) {
59 return;
60 }
61
62 if (m_StateLevel >= MAX_NESTED_EVENTS) {
63 FATAL_NOLOCK("Execution-context cleanup recorded an invalid state level");
64 return;
65 }
66
67 m_Thread->m_StateLevels[m_StateLevel].m_ExecutionContext.restore(m_Previous);
68 m_Thread = nullptr;
69}
ExecutionContext enter(ExecutionContext context)
static bool getInterrupts()
static ProcessorInformation & information()
static void setInterrupts(bool bEnable)
size_t m_nStateLevel
Definition Thread.h:1177
ExecutionContextState m_ExecutionContext
Definition Thread.h:1152