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